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 。

  • 相关阅读:
    C++11 Lambda表达式
    C++ 容器操作
    C/C++ 动态存储分配 malloc calloc realloc函数的用法与区别
    使用visual C++测试
    设计模式有感
    smartProgram学习笔记
    C++析构函数
    C++指针和引用
    Python机器学习笔记:常用评估模型指标的用法
    Python机器学习笔记:不得不了解的机器学习面试知识点(1)
  • 原文地址:https://www.cnblogs.com/sand-tiny/p/3962888.html
Copyright © 2011-2022 走看看