java多线程中的同步技术
线程安全问题的引出
当执行程序时,会有多个线程一起抢夺cpu资源,谁抢到了谁就执行run方法
而当程序操作共享数据的时候,会出现线程安全问题,即多个子线程同时修改同一份数据,造成了数据的错误
public static int sum = 100;
@Override
public void run() {
while(true) {
if(sum>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖出第"+sum+"张票");
sum--;
}else {
break;
}
}
}
当有三个线程执行此卖票任务时
TicketThread thread = new TicketThread();
new Thread(thread,"窗口一").start();
new Thread(thread,"窗口二").start();
new Thread(thread,"窗口三").start();
这三个进程会抢夺买票任务的执行权,如设置三个子线程为t0,t1,t2
当t0抢到了cpu的执行权后,会进入到run方法执行卖票任务,执行到if语句后会进行10ms的睡眠,此时会放弃对cpu的占用,转而交给t1或t2去执行,此时另外两个子线程会轮流拿到cpu的执行权,但假如此时票数仅剩一张,t0,t1,t2睡醒后都会进行票数的打印功能和自减,所以可能会出现如下情况
或者三个线程会同时运行到票数打印语句形成如下情况
这就是出现了所谓的线程安全问题,解决线程安全问题就会用到同步技术
java多线程中的同步技术
同步技术的原理:
使用了一个锁对象,也叫同步锁,对象锁,对象监视器
public static int sum = 100;
@Override
public void run() {
while(true) {
synchronized (Object.class) {
if(sum>0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在卖出第"+sum+"张票");
sum--;
}else {
break;
}
}
}
}
假如此时t0抢夺到了cpu的执行权,会执行run方法,当遇到synchronized代码块后,会检查synchronized代码块是否有锁对象,如果有,就会获取到锁对象并且进入到同步代码块中执行,执行完毕后会交还锁对象
此时t1如果也抢到了cpu的执行权,会运行run方法,当遇到synchronized代码块后同样会检查有没有锁对象,当发现没有时线程就会阻塞,等待t0执行完成后交还锁对象,此时t1才会执行,t2同t1
这时候就会发现在同一时刻只有一个线程在操作共享数据,不会出现多个线程同时修改同一份数据的情况导致不可预料的错误,这就是同步技术解决线程安全问题,程序在运行的时候会频繁的判断锁,获取锁,释放锁,程序的效率会降低