线程安全问题引发需满足三个条件:
- 多线程环境
- 有共享数据
- 有多条语句操作共享数据
分析代码示例:
以下代码演示了 100 个线程同时对 count 执行自增操作,操作结束之后它的值有可能小于 100。
package com.demo.controller.line;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UnsafeExemple {
public class Exemple{
private int count=0;
public void add(){
count++;
System.out.println(count);
}
public int res(){
return count;
}
}
public static void main(String[]args)throws InterruptedException{
UnsafeExemple e=new UnsafeExemple();
Exemple exemple=e.new Exemple();
CountDownLatch countDownLatch=new CountDownLatch(100);
ExecutorService executorService= Executors.newCachedThreadPool();
for(int i=0;i<100;i++){
executorService.execute(()->{ exemple.add(); });
countDownLatch.countDown();
}
countDownLatch.await();
executorService.shutdown();
}
}
部分输出结果: 可以明显看到,并不是预期中的0-100按顺序显示
解决线程不安全的方法为对add()方法上锁
package com.demo.controller.line;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UnsafeExemple {
public class Exemple{
private int count=0;
public synchronized void add(){
count++;
System.out.println(count);
}
public int res(){
return count;
}
}
public static void main(String[]args)throws InterruptedException{
UnsafeExemple e=new UnsafeExemple();
Exemple exemple=e.new Exemple();
CountDownLatch countDownLatch=new CountDownLatch(100);
ExecutorService executorService= Executors.newCachedThreadPool();
for(int i=0;i<100;i++){
executorService.execute(()->{ exemple.add(); });
countDownLatch.countDown();
}
countDownLatch.await();
executorService.shutdown();
}
}
部分输出结果: 可以明显看到结果是按照预期显示的 ~
当然这只是一种很简单的java自带的关键字synchronized加锁方式,如果让小哥哥/小姐姐学到东西了,点个赞再走吧 ~
后续还会分享很多的学习笔记,加关注不迷路 ~