并发编程小结

时间:2019-04-15
本文章向大家介绍并发编程小结,主要包括并发编程小结使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

用代码描述这么一个场景,在main方法中开启两个线程,其中一个线程t1往list里循环添加元素,另一个线程t2监听list中的size,当size等于5时,t2线程结束,t1线程继续执行,直到循环结束,试着想一想,以下代码能不能实现:

 1 package com.fanjf.thread;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class Mycontainer {
 7     static List<Integer> integers = new ArrayList<>();
 8         
 9     public static void main(String[] args) {
10         new Thread(new Runnable() {
11             public void run() {
12                 System.out.println("t1启动");
13                 for(int i=0;i<10;i++){
14                     integers.add(i);
15                     try {
16                         Thread.sleep(1000);
17                     } catch (InterruptedException e) {
18                         e.printStackTrace();
19                     }
20                     System.out.println("add:"+i);
21                 }
22                 System.out.println("t1结束");
23             }
24         }).start();
25         
26         new Thread(new Runnable() {
27             public void run() {
28                 System.out.println("t2启动");
29                 while(true){
30                     if(integers.size()==5){
31                         break;
32                     }
33                 }
34                 
35                 System.out.println("t2结束");
36             }
37             
38         }).start();
39     }
40 
41 }

输出结果如下,且程序并没有结束,一直处于运行状态

t1启动
t2启动
add:0
add:1
add:2
add:3
add:4
add:5
add:6
add:7
add:8
add:9
t1结束

有并发编程经验的人应该很容易就能看出问题所在,这里涉及到了线程之间的可见性问题,只需要在上面第7行的integers变量前加上volatile便可以得到想要的结果,如下红色部分:

volatile static List<Integer> integers = new ArrayList<>();

输出结果如下:

t1启动
t2启动
add:0
add:1
add:2
add:3
t2结束
add:4
add:5
add:6
add:7
add:8
add:9
t1结束她

这里的volatile作用是为了保证线程之间的可见性,java之间线程之间通信是通过共享内存来实现的,当t1线程向integers中add元素时,如果不加volatile,这个size的变化t2线程是无法感知的,因为当线程执行时,t2会在执行当前线程的cpu中缓存一份integers,t2会优先读取自己线程本地变量的integers,而不从主内存中读取,也就是两个线程之间是不可见的,当在这个共享变量加上volatile时,t1向integers中add元素,即修改了共享变量integers的值,程序会通知t2重新从主内存中读取共享变量的值,这时候t1和t2之间就是可见的,这其实是happens before规则中其中重要的一条:volatile的写happens before volatile的读,意思就是说一个线程对volatile修饰的变量的写操作对于其他线程来说一定是可见的,感兴趣的可以自己了解一下happens before规则。