高并发-volatile

synchronized是阻塞式同步,在线程竞争激烈的情况下会升级为重量级锁。而volatile可以说是java虚拟机提供的最轻量级的同步机制。

根据Java内存模型,各个线程会将共享变量从主内存中拷贝到工作内存,然后执行引擎会基于工作内存中的数据进行操作处理。线程在工作内存进行操作后何时写到主内存是不确定的。volatile修饰的变量给java虚拟机特殊的约定,线程对volatile变量的修改会立刻被其他线程所感知,不会出现数据脏读的现象,从而保证数据的“可见性”。被volatile修饰的变量确保每个线程能够获取该变量的最新值

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.bjsxt.base.sync007;
 
public class RunThread extends Thread{
 
    private volatile boolean isRunning = true;
    private void setRunning(boolean isRunning){
        this.isRunning = isRunning;
    }
     
    public void run(){
        System.out.println("进入run方法.."+Thread.currentThread().getName());
        int i = 0;
        while(isRunning == true){
            //..
//          System.out.println("线程是否开启:"+isRunning);
        }
        System.out.println("线程停止.."+Thread.currentThread().getName());
    }
     
    public static void main(String[] args) throws InterruptedException {
        RunThread rt = new RunThread();
        rt.start();
        Thread.sleep(10);
        rt.setRunning(false);
        System.out.println("isRunning的值已经被设置了false.."+Thread.currentThread().getName());
    }
}

 打印

1
进入run方法..Thread-0<br>isRunning的值已经被设置了false..main<br>线程停止..Thread-0

 例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.bjsxt.base.conn008;
 
import java.util.ArrayList;
import java.util.List;
 
public class ListAdd1 {
 
     
    private volatile static List list = new ArrayList();   
     
    public void add(){
        list.add("bjsxt");
    }
    public int size(){
        return list.size();
    }
     
    public static void main(String[] args) {
         
        final ListAdd1 list1 = new ListAdd1();
         
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for(int i = 0; i <10; i++){
                        list1.add();
                        System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                        Thread.sleep(500);
                    }  
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1");
         
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    if(list1.size() == 5){
                        System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");
                        throw new RuntimeException();
                    }
                }
            }
        }, "t2");      
         
        t1.start();
        t2.start();
    }
     
     
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
Exception in thread "t2" java.lang.RuntimeException
    at com.bjsxt.base.conn008.ListAdd1$2.run(ListAdd1.java:43)
    at java.lang.Thread.run(Unknown Source)
当前线程收到通知:t2 list size = 5 线程停止..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..

 例2 使用wait 和 notify  , 配合synchronized关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.bjsxt.base.conn008;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
/**
 * wait notfiy 方法,wait释放锁,notfiy不释放锁
 *
 */
public class ListAdd2 {
    private volatile static List list = new ArrayList();   
     
    public void add(){
        list.add("bjsxt");
    }
    public int size(){
        return list.size();
    }
     
    public static void main(String[] args) {
         
        final ListAdd2 list2 = new ListAdd2();
         
        // 1 实例化出来一个 lock
        // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用
        final Object lock = new Object();
         
        final CountDownLatch countDownLatch = new CountDownLatch(1);
         
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (lock) {
                        for(int i = 0; i <10; i++){
                            list2.add();
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                            Thread.sleep(500);
                            if(list2.size() == 5){
                                System.out.println("已经发出通知..");
//                              countDownLatch.countDown();
                                lock.notify();
                            }
                        }                      
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
            }
        }, "t1");
         
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    if(list2.size() != 5){
                        try {
                            System.out.println("t2进入...");
                            lock.wait();
//                          countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
                    throw new RuntimeException();
                }
            }
        }, "t2");  
         
        t2.start();
        t1.start();
         
    }
     
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
t2进入...
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
已经发出通知..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t2收到通知线程停止..
Exception in thread "t2" java.lang.RuntimeException
    at com.bjsxt.base.conn008.ListAdd2$2.run(ListAdd2.java:71)
    at java.lang.Thread.run(Unknown Source)

 例3 countDownLatch

 

 

 



posted @   hy叶子  阅读(188)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示