Java多线程不同步造成的安全问题解决方案
当多个线程调用和修改同一个数据时,有可能出现上一个线程的数据正在修改的时候,下一个线程也进来修改数据, 此时后进的线程可能会拿着过时的数据修改,产生数据的安全问题.
public class SecondThread {
public static void main(String[] args) {
//3.创建实现类的对象
MyThread2 t2 = new MyThread2();
//4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
Thread s1 = new Thread(t2);
Thread s2 = new Thread(t2);
Thread s3 = new Thread(t2);
s1.setName("窗口一");
s2.setName("窗口二");
s3.setName("窗口三");
//5.通过Thread类的对象调用start()
s1.start();
s2.start();
s3.start();
}
}
/**
* 1.创建一个实现了runnable接口的类
* 2.实现类去实现runnable中的抽象方法run
* 3.创建实现类的对象
* 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
* 5.通过Thread类的对象调用start()
*/
//1.创建一个实现了runnable接口的类
class MyThread2 implements Runnable {
//2.实现类去实现runnable中的抽象方法run
private int ticket = 100;
@Override
public void run() {
while (true) {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "卖票了,号码为" + ticket);
ticket--;
} else {
break;
}
}
}
}
结果部分片段如下显示:
窗口一卖票了,号码为100
窗口一卖票了,号码为99
窗口一卖票了,号码为98
窗口一卖票了,号码为97
窗口一卖票了,号码为96
窗口二卖票了,号码为100
明显可以看出,一号窗口和二号窗口同时卖出了一张号码为100的票
面对这个问题,有两种解决方案选择:
一、同步代码块
synchronized(同步监视器){
//需要被同步的代码
}
说明:
- 操作共享数据的代码,即为需要被同步的代码
- 共享数据:多个线程共同操作的变量,比如:ticket就是共享数据
- 同步监视器,俗称:锁。任何一个类的对象,都可以充当锁
要求:多个线程必须共用同一把锁
好处:消除了因为代码不及时更新带来的影响。
坏处:因为中间同步代码块的原因导致synchronized内部的代码执行起来依然成为了单线程模式,操作同步代码时,只有一个线程参与,其他线程只能等待。
二、同步方法
如果操作共享数据的代码完整的生命在一个方法中,我们不妨将此方法声明为同步的。
同步方法操作很简单,只需要将需要同步的方法的修饰符写上synchronized即可
private synchronized void show(){
//同步代码块
}
此时,同步监视器为默认的this。

浙公网安备 33010602011771号