解决线程安全的几种方式
一、解决线程安全总体可分为两大类:
1.使用synchronized关键字(可修饰代码块或方法)
(1)使用synchronized关键字修饰代码块
public class ThreadDemo {
public static void main(String[] args) {
ThreadSafe1 thread = new ThreadSafe1();
Thread t1 = new Thread(thread);
Thread t2 = new Thread(thread);
Thread t3 = new Thread(thread);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class ThreadSafe1 implements Runnable{
//定义车票的数量
private int ticket = 100;
@Override
public void run() {
while(true) {
synchronized(ThreadSafe1.class) { //同步监视器为ThreadSafe1.class,它只加载一次,是唯一的,该同步代码块里包含着共享数据的操作
if(ticket > 0) {
System.out.println(Thread.currentThread().getName()+":"+"出售第"+ticket+"张车票");
//车票数量减一
ticket--;
}else {
break;
}
}
}
}
}
(2)使用synchronized关键字修饰方法
public class ThreadDemo {
public static void main(String[] args) {
ThreadSafe2 thread = new ThreadSafe2();
Thread t1 = new Thread(thread);
Thread t2 = new Thread(thread);
Thread t3 = new Thread(thread);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class ThreadSafe2 implements Runnable{
//定义车票的数量
private int ticket = 100;
@Override
public void run() {
while(true) {
//调用窗口售票方法
sale();
if(ticket == 0) {
break;
}
}
}
//实现窗口售票
public synchronized void sale() { //该方法的同步监视器为ThreadSafe2的对象,它是唯一的,这里面也存放着对共享数据的操作
if(ticket > 0) {
System.out.println(Thread.currentThread().getName()+":"+"出售第"+ticket+"张车票");
//车票数量减一
ticket--;
}
}
}
2.使用Lock锁方式解决线程安全问题
public class ThreadDemo {
public static void main(String[] args) {
ThreadSafe3 thread = new ThreadSafe3();
Thread t1 = new Thread(thread);
Thread t2 = new Thread(thread);
Thread t3 = new Thread(thread);
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class ThreadSafe3 implements Runnable{
//定义车票的数量
private int ticket = 100;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while(true) {
try {
lock.lock(); //对对操作共享数据的代码进行加锁
//进行线程休眠,增加其他线程调用的机会
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(ticket > 0) {
System.out.println(Thread.currentThread().getName()+":"+"出售第"+ticket+"张车票");
//车票数量减一
ticket--;
}else {
break;
}
}finally {
lock.unlock(); //进行解锁
}
}
}
}
二、synchronized关键字与Lock锁方式的区别
(1)两者都可以解决线程安全问题
(2)synchronized关键字既可以修饰代码块又可以修饰方法;而Lock锁方式只可以修饰代码块
(3)synchronied关键字修饰的代码块或方法在运行结束后,会自动释放锁;而Lock锁方式需手动为代码块加锁并释放锁
(4)从性能上,Lock锁方式优于synchronized关键字

浙公网安备 33010602011771号