什么是线程安全
当多个线程对同一个资源进行访问的时候,可能出现非原子性操作,造成数据出现意想不到的结果。
多线程抢夺资源案例代码
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();
}