JAVA基础之多线程三期--线程安全问题
一、线程安全问题就是指:多个线程并发访问同一个资源而发生安全性的问题,
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写 操作,一般来说,这个全局变量是线程安全的;
若有多个线程同时执行写操作,一般都需要考虑线程同步, 否则的话就可能影响线程安全。
问题出现:
public class ThreadSafe implements Runnable {
private int ticket = 100;
/**
* 执行买票
*/
public void run() {
while (true){
if(ticket>0){
//提高线程安全问题出现概率,让他睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
ticket--;
}
}
}}
public class ThreadSafeTest {
public static void main(String[] args) {
//创建target目标实现类
ThreadSafe threadSafe = new ThreadSafe();
//开启三个线程窗口,必须三个线程实例对象共享一个目标对象,才能保证票数就三百张
Thread th1 = new Thread(threadSafe,"窗口一");
Thread th2 = new Thread(threadSafe,"窗口二");
Thread th3 = new Thread(threadSafe,"窗口三");
th1.start();
th2.start();
th3.start();
}
}
二、窗口1线程进入操作的时候,窗口2和窗口3线程只能在外等着,窗口1操作结束,窗口1和窗口2和窗口3才有机会进入代码 去执行。也就是说在某个线程修改共享资源的时候,其他线程不能修改该资源,等待修改完毕同步之后,才能去抢夺CPU 资源,完成对应的操作,保证了数据的同步性,解决了线程不安全的现象
三、引用同步机制解决线程安全问题
1. 同步代码块。 2. 同步方法。 3. 锁机制
A、同步代码块
格式:
synchronized(同步锁){
需要同步操作的代码
}
同步锁: 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
1. 锁对象 可以是任意类型。
2. 多个线程对象 要使用同一把锁
3. 锁对象的作用:把同步代码块锁住,只允许一个线程在同步代码块上执行
测试:
public class ThreadSafe implements Runnable {
private int ticket = 100;
Object obj = new Object();
/**
* 执行买票
*/
public void run() {
while (true){
synchronized (obj){
if(ticket>0){
//提高线程安全问题出现概率,让他睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
ticket--;
}
}
}
}
}
3. Lock(锁)
Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock() :加同步锁。
public void unlock() :释放同步锁
使用步骤:
1.在成员变量位置创建一个ReentrantLock()对象;
2.在可能出现安全问题的代码前调用Lock接口中的方法lock()
3.在可能出现安全问题的代码后调用Lock接口中的方法unlock()
public class ThreadSafe1 implements Runnable {
private int ticket = 100;
Lock lock = new ReentrantLock();
/**
* 执行买票
*/
public void run() {
while (true){
lock.lock();
if(ticket>0){
//提高线程安全问题出现概率,让他睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 正在卖第:"+ticket+"票");
ticket--;
}
lock.unlock();
}
}
}