Java线程安全 关于原子性与volatile的试验

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java线程安全 关于原子性与volatile的试验相关的知识,希望对你有一定的参考价值。

1. 变量递增试验

 1     static /*volatile*/ int shared=0;//volatile也无法保证++操作的原子性
 2     static synchronized int incrShared(){//不加synchronized的话,shared最终结果值小于预期
 3         return ++shared;
 4     }
 5     public static void testIncrShared(String[] args) throws InterruptedException {
 6         shared=0;
 7         Thread[] thrds = new Thread[20];
 8         for(int j=0;j<thrds.length;j++){
 9             thrds[j] = new Thread(new Runnable() {
10                 @Override
11                 public void run() {
12                     for(int k=0;k<1000;k++){
13                         System.out.println(incrShared());
14                     }
15                 }
16             });
17         }
18         for(int j=0;j<thrds.length;j++){
19             thrds[j].start();
20         }
21         for(int j=0;j<thrds.length;j++){
22             thrds[j].join();
23         }
24         System.out.println(shared);
25     }

2. volatile试验

 1     static /*volatile*/ int a0,a1;//这里加volatile的话,可以避免r0==r1==0的结果
 2     static /*volatile*/ int r0,r1;//这里即使加volatile,也无法避免r0==r1==0的结果
 3     public static void testVolatile(String[] args) throws InterruptedException {
 4         int[] a=new int[2];
 5         int[] r=new int[2];
 6         final int SLEEP=10;
 7         final Object lock=new Object();
 8         Runnable run1=new Runnable() {
 9             @Override
10             public void run() {
11                 try {
12                     Thread.sleep(SLEEP);
13                 } catch (InterruptedException e) {
14                     e.printStackTrace();
15                 }
16                 //synchronized (lock) {//加锁也可以建立happens-before关系,避免r0==r1==0的结果
17                     a0=1;
18                 //}
19                 r1=a1;
20             }
21         };
22         Runnable run2=new Runnable() {
23             @Override
24             public void run() {
25                 try {
26                     Thread.sleep(SLEEP);
27                 } catch (InterruptedException e) {
28                     e.printStackTrace();
29                 }
30                 //synchronized (lock) {
31                     a1=1;
32                 //}
33                 r0=a0;
34             }
35         };
36         Thread thrd1;
37         Thread thrd2;
38         
39         int i;
40         int[][] acnt=new int[2][2];
41         int[][] rcnt=new int[2][2];
42         for(i=0;i<10000;i++){
43             a0=a1=0;
44             r0=r1=0;
45             thrd1 = new Thread(run1);
46             thrd2 = new Thread(run2);
47             
48             thrd1.start();
49             thrd2.start();
50             
51             thrd1.join();
52             thrd2.join();
53             
54             a[0]=a0;
55             a[1]=a1;
56             r[0]=r0;
57             r[1]=r1;
58             System.out.println(i);
59             System.out.println(Arrays.toString(a));
60             System.out.println(Arrays.toString(r));
61             acnt[a[0]][a[1]]++;
62             rcnt[r[0]][r[1]]++;
63         }
64         System.out.println(Arrays.deepToString(acnt));
65         System.out.println(Arrays.deepToString(rcnt));
66     }

 

3. volatile试验2

 1     static boolean shouldStop=false;
 2     public static void testVolatile2(String[] args) throws InterruptedException {
 3         shouldStop=false;
 4         Runnable run1=new Runnable() {
 5             @Override
 6             public void run() {
 7                 int i=0;
 8                 while (!shouldStop) {//无法读取到线程2修改后的shouldStop值,导致无限循环
 9                     i++;
10                     //System.out.println(i);//如果调用其他函数的话,就又可以读取到shouldStop的最新值了
11                 }
12             }
13         };
14         Runnable run2=new Runnable() {
15             @Override
16             public void run() {
17                 try {
18                     Thread.sleep(10);
19                 } catch (InterruptedException e) {
20                     e.printStackTrace();
21                 }
22                 shouldStop=true;
23             }
24         };
25         Thread thrd1;
26         Thread thrd2;
27         
28         int i;
29         int[][] acnt=new int[2][2];
30         int[][] rcnt=new int[2][2];
31         for(i=0;i<100;i++){
32             thrd1 = new Thread(run1);
33             thrd2 = new Thread(run2);
34             
35             thrd1.start();
36             thrd2.start();
37 
38             thrd2.join();
39             System.out.println(i);
40             System.out.println(shouldStop);
41             thrd1.join();
42             
43         }
44     }

 

以上是关于Java线程安全 关于原子性与volatile的试验的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程之三volatile与等待通知机制示例

Java并发编程原子性与易变性

volatile关键字解释和使用

Java 并发编程线程锁机制 ( 线程安全 | 锁机制 | 类锁 | 对象锁 | 轻量级锁 | 重量级锁 )

转Java线程安全

线程安全的三大特性(原子性可见性有序性)volatile关键字