zoukankan      html  css  js  c++  java
  • java多线程总结四:volatile、synchronized示例

    1、synchronized保证同步

    先看一个生成偶数的类

    1. <span style="font-size:16px;">package demo.thread;  
    2.   
    3. /** 
    4.  *这是一个int生成器的抽象类 
    5.  *  
    6.  */  
    7. public abstract class IntGenerator {  
    8.       
    9.     private volatile boolean canceled = false;  
    10.   
    11.     public abstract int next();  
    12.   
    13.     public void cancel() {  
    14.         canceled = true;  
    15.     }  
    16.   
    17.     public boolean isCanceled() {  
    18.         return canceled;  
    19.     }  
    20. }  
    21. </span>  


     

    1. <span style="font-size:16px;">/* 
    2.  * 产生偶数 
    3.  */  
    4. class EvenGenerator extends IntGenerator {  
    5.     private int currentEvenValue = 0;  
    6.     String s = "";  
    7.   
    8.     @Override  
    9.     public int next() {  
    10.         <span style="color:#ff0000;">synchronized </span>(s) {  
    11.             ++currentEvenValue;  
    12.             ++currentEvenValue;  
    13.             return currentEvenValue;  
    14.         }  
    15.     }  
    16.   
    17. //  //这样也可以  
    18. //  public <span style="color:#ff0000;">synchronized </span>int next() {  
    19. //          ++currentEvenValue;  
    20. //          ++currentEvenValue;  
    21. //          return currentEvenValue;  
    22. //  }  
    23. }</span>  


    注意到在产生偶数是要加同步锁,否则可能线程1刚好执行了一句++currentEvenValue;操作,就被线程2抢去了cpu,此时线程2执行return currentEvenValue;这时返回的就是一个奇数。加synchronized 就是两个线程同时只能一个线程执行synchronized 块的代码。

    测试代码:

    1. <span style="font-size:16px;">package demo.thread;  
    2.   
    3. import java.util.concurrent.ExecutorService;  
    4. import java.util.concurrent.Executors;  
    5.   
    6. /* 
    7.  * 消费数字 
    8.  */  
    9. public class EvenChecker implements Runnable {  
    10.       
    11.     private IntGenerator generator;  
    12.     private final int id;  
    13.   
    14.     public EvenChecker(IntGenerator g, int ident) {  
    15.         generator = g;  
    16.         id = ident;  
    17.     }  
    18.   
    19.     public void run() {  
    20.         while (!generator.isCanceled()) {  
    21.             int val = generator.next();  
    22.             if (val % 2 != 0) {//如果不是偶数  
    23.                 System.out.println(val + " not enen!");  
    24.                 generator.cancel();  
    25.             }  
    26.         }  
    27.     }  
    28.   
    29.     public static void test(IntGenerator gp, int count) {  
    30.         ExecutorService exec = Executors.newCachedThreadPool();  
    31.         for (int i = 0; i < count; i++)  
    32.             exec.execute(new EvenChecker(gp, i));  
    33.         exec.shutdown();  
    34.     }  
    35.   
    36.     public static void test(IntGenerator gp) {  
    37.         test(gp, 10);  
    38.     }  
    39.   
    40.     public static void main(String[] args) {  
    41.         test(new EvenGenerator());  
    42.     }  
    43. }</span>  


    分析:如果产生偶数的类未加synchronized,那么测试程序将会出现奇数导致退出程序。

     

    2、volatile表示原子性,可见性。

          对于多个线程之间共享的变量,每个线程都有自己的一份拷贝,当线程1改变变量值时,其他线程并不马上知道该变量值改变了,volatile就保证了变量值对各个线程可见,一个线程改变该值,马上其他线程中该值也改变。原子性表明操作不可中断,如基本变量赋值。

         代码示例:

    1. <span style="font-size:16px;">package demo.thread;  
    2.   
    3. public class VolatileDemo implements Runnable {  
    4.       
    5.     private volatile int i = 0;//volatile设置可见性  
    6.   
    7.     public synchronized  int getValue() {  
    8.         return i;  
    9.     }  
    10.   
    11.     private synchronized void enenIncrement() {  
    12.         i++;  
    13.         i++;  
    14.     }  
    15.   
    16.     @Override  
    17.     public void run() {  
    18.         while (true)  
    19.             enenIncrement();  
    20.     }  
    21.   
    22.     public static void main(String[] args) {  
    23.         VolatileDemo at = new VolatileDemo();  
    24.         new Thread(at).start();  
    25.         while (true) {  
    26.             int val = at.getValue();  
    27.             if (val % 2 != 0) {//出现奇数,退出程序  
    28.                 System.out.println(val+" is not enen!");  
    29.                 System.exit(0);  
    30.             }  
    31.         }  
    32.   
    33.     }  
    34. }  
    35. </span>  


    注意i++操作并不是原子行操作,getValue() 方法也要加synchronized 。

  • 相关阅读:
    POJ 3268 Silver Cow Party (Dijkstra)
    怒学三算法 POJ 2387 Til the Cows Come Home (Bellman_Ford || Dijkstra || SPFA)
    CF Amr and Music (贪心)
    CF Amr and Pins (数学)
    POJ 3253 Fence Repair (贪心)
    POJ 3069 Saruman's Army(贪心)
    POJ 3617 Best Cow Line (贪心)
    CF Anya and Ghosts (贪心)
    CF Fox And Names (拓扑排序)
    mysql8.0的新特性
  • 原文地址:https://www.cnblogs.com/sand-tiny/p/3962888.html
Copyright © 2011-2022 走看看