线程安全问题产生的原理
出现了线程安全问题 卖票出现了重复的票
图解
线程同步
当我们使用多个线程访问同一个资源的时候 且多个线程对资源有写的操作 就容易出现线程安全问题
要解决上诉多线程并发访问一个资源的安全性问题 也就是解决重复票 java中提供了同步机制
(synchronized)来解决
有三种方法来完成同步操作:
1.同步代码块
2.同步方法
3.锁机制
同步代码块
同步代码块:synchronized关键字可以用于方法中的某个区块中 表示这个区块的资源实现互斥访问
格式:
synchronized(同步锁){ 需要同步操作的代码 }
同步锁:
对象的同步锁只是一个感念 可以想象为在对象上标记了一个锁
1.锁对象 可以是任意类型
2.多个线程对象 要使用同一把锁
注意:在任何时候 最多允许一个线程拥有同步锁 谁拿到锁就进入代码块 其他的线程只能在外等着
锁对象作用:把同步代码块锁住 只让一个线程在同步代码块中执行
代码:
package demo19;
public class DemoSynchronized implements Runnable {
//定义一个多个线程共享的票源
private int ricket=100;
//创建锁对象
Object obj = new Object();
//设置线程任务:卖票
@Override
public void run() {
//使用死循环 让卖票操作重复执行
while (true){
//同步代码块
synchronized (obj){
//加入线程休眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//先判断票是否存在
if (ricket==0){
break;
}
//票存在 买票 ticket--
System.out.println(Thread.currentThread().getName()+"--->正在买第"+ricket+"张票");
ricket--;
}
}
}
}
class test07{
public static void main(String[] args) {
//创建实现类对象
DemoSynchronized ticket = new DemoSynchronized();
//实现线程执行
/*
因为有两张售票口所有要进行出售
*/
new Thread(ticket).start();
new Thread(ticket).start();
}
}
运行结果:‘
使用了一个锁对象 这个锁对象叫做同步锁 也叫对象锁 也叫对象监视器
2个线程一起抢夺cpu的执行权 谁抢到了谁执行run方法进行买票
比如:
- 第一个线程抢到了cpu的执行权 执行run方法 遇到代码块这时第一个线程会检查同步代码块是否有锁对象
- 发现有就会获取锁对象 进入到同步中执行
- 第二个线程抢到了cpu的执行权 执行run方法 遇到代码块 这时第二个线程会检查同步代码块是否有锁对象
- 发现没有 就会进入堵塞状态 会一直到第一个线程执行完将锁对象还给同步代码块时 第二个线程才执行