线程安全问题和解决方案
程序员文章站
2022-07-14 10:41:13
...
什么是线程安全
当多个线程对同一个资源进行访问的时候,可能出现非原子性操作,造成数据出现意想不到的结果。
多线程抢夺资源案例代码
package com.shopping.thread;
import java.util.concurrent.CountDownLatch;
public class ShareData {
private int count;
public void increment() {
count++;
}
public int getCount() {
return count;
}
public static void main(String[] args) {
final ShareData shareData = new ShareData();
//设置线程数量
final int threadNum = 100;
//发令枪,起到倒计时器的作用。cdl.await会让所有线程等待,只有当计数减到为0时,
//所有线程并发执行。
final CountDownLatch cdl = new CountDownLatch(threadNum);
for (int i = 0; i < threadNum; i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 1000; j++) {
shareData.increment();
}
//计数减一
cdl.countDown();
}
}).start();
}
try {
//cdl.await会让所有线程等待,只有当计数减到为0时,所有线程并发执行。
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(shareData.getCount());
}
}
因为线程抢夺资源的问题造成输出的结果小于100000(期望结果是100000)
出现的问题分析
public void increment() {
count++;
}
代码中的count++并非原子性操作
第一种解决方案
使用线程同步synchronized
public synchronized void increment() {
count++;
}
第二种解决方案
使用线程锁Lock
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
第三种解决方案
使用并发库中的AtomicInteger
private AtomicInteger count=new AtomicInteger();
public void increment() {
count.addAndGet(1);
}
public int getCount() {
return count.get();
}
上一篇: PV操作与信号量
下一篇: java个人笔记之 i++ 线程不安全
推荐阅读
-
Android 入门第十讲02-广播(广播概述,使用方法(系统广播,自定义广播,两个activity之间的交互和传值),EventBus使用方法,数据传递,线程切换,Android的系统广播大全)
-
完美解决Java中的线程安全问题
-
java 线程安全和不可变性
-
分享15个优秀的 CSS 解决方案和工具 - 梦想天空(山边小溪)
-
C#线程 BeginInvoke和EndInvoke使用方法
-
生产消费者模式实现方式和线程安全问题代码示例
-
Java终止线程实例和stop()方法源码阅读
-
Java中启动线程start和run的两种方法
-
Java线程之线程同步synchronized和volatile详解
-
MySQL多线程复制遇到Error_code: 1872的解决方案