zoukankan      html  css  js  c++  java
  • 对象锁的同步与异步

    同步:synchronized

      同步的概念就是共享 , 如果不是共享的资源 , 就没有必要进行同步。

    异步:asynchronized

      异步的概念就是独立 , 相互之间不受到任何制约。

    同步的目的就是为了线程安全 , 其实对于线程安全来说 , 需要满足两个特性:

    • 原子性 (同步):同步性就是一个事物要么一起成功,要么一起失败。
    • 可见性:就是一个线程的操作可以及时被其他线程感知到。
     1 package com.itdoc.multi.sync003;
     2 
     3 /**
     4  * 对象锁的同步与异步
     5  *
     6  * @author Wáng Chéng Dá
     7  * @create 2017-03-20 11:36
     8  */
     9 public class MyObject {
    10 
    11     public synchronized void method1() {
    12         try {
    13             System.out.println(Thread.currentThread().getName());
    14             Thread.sleep(5000);
    15         } catch (InterruptedException e) {
    16             e.printStackTrace();
    17         }
    18     }
    19 
    20     public synchronized void method2() {
    21 
    22         try {
    23             System.out.println(Thread.currentThread().getName());
    24             Thread.sleep(1000);
    25         } catch (InterruptedException e) {
    26             e.printStackTrace();
    27         }
    28     }
    29 
    30     public static void main(String[] args) {
    31         final MyObject mo = new MyObject();
    32 
    33         /**
    34          * 分析:
    35          * t1 线程先持有对象锁, t2 线程可以以异步的方式调用对象中的非 synchronized 修饰的方法。
    36          * t1 线程现持有对象锁, t2 线程若是要调用对象中的同步方法 (synchronized 修饰的方法),
    37          * 需要等 t1 线程之行结束将对象锁释放后才开始执行 (同步)。
    38          * 若是静态方法 .class 类锁, 效果一样。
    39          * 注意: 线程之间必须是相同的锁才可谈论异步同步问题。
    40          */
    41         Thread t1 = new Thread(new Runnable() {
    42             @Override
    43             public void run() {
    44                 mo.method1();
    45             }
    46         }, "T1");
    47 
    48         Thread t2 = new Thread(new Runnable() {
    49             @Override
    50             public void run() {
    51                 mo.method2();
    52             }
    53         }, "T2");
    54         t1.start();
    55         t2.start();
    56     }
    57 }

     脏读:

     1 package com.itdoc.multi.sync004;
     2 
     3 /**
     4  * 业务整体需要使用完整的 synchronized, 保持业务的原子性。
     5  *
     6  * @author Wáng Chéng Dá
     7  * @create 2017-03-20 13:52
     8  */
     9 public class DirtyRead {
    10 
    11     private String username = "z3";
    12 
    13     private String password = "123";
    14 
    15     public synchronized void setValue(String username, String password) {
    16         this.username = username;
    17         try {
    18             Thread.sleep(4000);
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22         this.password = password;
    23         System.out.println("setValue 最终结果: username = " + username + " -- password = " + password);
    24     }
    25 
    26     public synchronized void getValue() {
    27         System.out.println("getValue 方法得到: username = " + this.username + " -- password = " + this.password);
    28     }
    29 
    30     public static void main(String[] args) throws InterruptedException {
    31         final DirtyRead dirtyRead = new DirtyRead();
    32         Thread t1 = new Thread(new Runnable() {
    33             @Override
    34             public void run() {
    35                 dirtyRead.setValue("z3", "456");
    36             }
    37         }, "T1");
    38         t1.start();
    39         Thread.sleep(1000);
    40         dirtyRead.getValue();
    41     }
    42 }

    若方法不同步 , 在 t1 线程执行睡眠时, 主线程已经执行完成 , 并打印出 getValue 方法得到: username = z3 -- password = 123 这种数据 , 只有方法同步 , 才能保持业务的原子性。

  • 相关阅读:
    Mybatis 与 spring mvc
    Extjs 表格横坐标显示问题
    Extjs 图片的自动缩放
    C# Winform 界面中各控件随着窗口大小变化
    spring 连接各种数据源的配置(转载)
    <转>(C#)WinForm窗体间传值
    java stack 底层详细
    java hashmap 底层详细
    java LinkedList 底层详细
    java ArrayList 底层详细
  • 原文地址:https://www.cnblogs.com/chinda/p/6588097.html
Copyright © 2011-2022 走看看