对象锁的同步与异步

同步: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 这种数据 , 只有方法同步 , 才能保持业务的原子性。

原文地址:https://www.cnblogs.com/chinda/p/6588097.html