解决线程安全问题的第一种方案: 使用同步代码块
格式:
synchronized(锁对象) {
可能会出现线程安全问题的代码 (访问了共享数据的代码)
}
注意: 代码块中的锁对象, 可以是任意对象, 但必须保证多个线程之间使用的是同一个
锁对象的作用是把同步代码块锁住, 同一时间只能让一个线程在同步代码块中执行
- package com.fgy.demo02;
- /**
- * 实现卖票案例
- */
- public class RunnableImpl implements Runnable {
- private int ticket = 100;
- Object obj = new Object();
- @Override
- public void run() {
- while (true) {
- synchronized (obj) {
- if (ticket> 0) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
- ticket--;
- }
- }
- }
- }
- }
- package com.fgy.demo02;
- public class Demo01Ticket {
- public static void main(String[] args) {
- RunnableImpl run = new RunnableImpl();
- new Thread(run).start();
- new Thread(run).start();
- new Thread(run).start();
- }
- }
解决线程安全问题的第二种方案: 使用同步方法
使用步骤:
1. 把访问了共享数据的代码抽取出来, 放到一个方法中
2. 在方法上添加 synchronized 修饰符
格式:
修饰符 synchronized 返回值类型 方法名 (...) {
可能会出现线程安全问题的代码 (访问了共享数据的代码)
}
同步方法的锁对象是: this
静态同步方法的锁对象不能是 this, 因为 this 是创建对象后产生的, 静态方法优先于对象
静态方法的锁对象是本类的 class 文件对象
- package com.fgy.demo03;
- /**
- * 实现卖票案例
- */
- public class RunnableImpl implements Runnable {
- private int ticket = 100;
- @Override
- public void run() {
- while (true) {
- payTicket();
- }
- }
- public synchronized void payTicket() {
- if (ticket> 0) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
- ticket--;
- }
- }
- }
解决线程安全问题的第三种方案: 使用 lock 锁
使用步骤:
1. 在成员位置创建 ReenterantLock 对象
2. 在可能出现安全问题的代码前调用 Lock 接口中的方法 lock() 获取锁
3. 在可能出现安全问题的代码后调用 Lock 接口中的方法 unlock() 释放锁
- package com.fgy.demo04;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- /**
- * 实现卖票案例
- */
- public class RunnableImpl implements Runnable {
- private int ticket = 100;
- Lock l = new ReentrantLock();
- /*@Override
- public void run() {
- while (true) {
- l.lock();
- if (ticket> 0) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
- ticket--;
- }
- l.unlock();
- }
- }*/
- @Override
- public void run() {
- while (true) {
- l.lock();
- if (ticket> 0) {
- try {
- Thread.sleep(100);
- System.out.println(Thread.currentThread().getName() + "正在买第" + ticket + "张票");
- ticket--;
- } catch (InterruptedException e) {
- e.printStackTrace();
- } finally {
- // 无论程序是否发生异常都会释放锁
- l.unlock();
- }
- }
- }
- }
- }
来源: http://www.bubuko.com/infodetail-3352002.html