- 多线程并发安全问题
简要说明:
* 当多个线程操作同一资源时,由于线程切换的不确定性,
* 会导致出现线程安全的问题
下面通过简单实例演示
案例场景:使用两个线程代表两个人一起去买衣服,服装店只有一个试衣间[公共的资源],规定试衣间一次只能一个人试衣服
(空间太小了吧),实际业务规则可以类比。
public class SyncDemo2 {
public static void main(String[] args) {
final Shop shop = new Shop();
Thread t1 = new Thread(){
@Override
public void run() {
shop.goShop();
}
};
Thread t2 = new Thread(){
@Override
public void run() {
shop.goShop();
}
};
t1.start();
t2.start();
}
}
class Shop{
public void goShop() {
try {
Thread t = Thread.currentThread();
System.out.println(t.getName() + ":正在挑选衣服...");
Thread.sleep(5000);
System.out.println(t.getName() + ":正在试衣服...");
Thread.sleep(5000);
System.out.println(t.getName() + ":结账离开");
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行上述程序控制台输出:会看到同时在试衣服的情况,即多个线程一起占有资源,在实际业务场景中会导致并发安全的。
对应上述的并发安全问题,通常的解决办法是对公共执行的部分使用synchronized加锁。
加锁后的代码如下所示
class Shop{
public void goShop() {
try {
Thread t = Thread.currentThread();
System.out.println(t.getName() + ":正在挑选衣服...");
Thread.sleep(5000);
synchronized(this){
System.out.println(t.getName() + ":正在试衣服...");
Thread.sleep(5000);
}
System.out.println(t.getName() + ":结账离开");
} catch (Exception e) {
e.printStackTrace();
}
}
}
再次执行程序:并发安全问题得到解决。
总结:多线程并发安全问题要找到最小的公共访问部分对其枷锁,有效缩小同步范围可以提高线程的并发效率。