java多线程安全解决方案_java解决多线程安全的方式

解决多线程安全问题的方式(加锁)包含以下几种:

synchronized关键字:又包含同步代码块,同步方法

Lock锁:

锁的分类: 类锁(class锁),对象锁

实例:现有如下代码,总共100张票,3个窗口同时售卖,这里采用实现Runnable接口的方式,还可以使用继承Thread方式实现,Runnable与Thread类详解

public class RunnableWindowTest{

public static void main(String[] args) {

RunnableWindow runnableWindow = new RunnableWindow();

new Thread(runnableWindow,"窗口1").start();

new Thread(runnableWindow,"窗口2").start();

new Thread(runnableWindow,"窗口3").start();

}

}

class RunnableWindow implements Runnable {

private int ticket=100;

@Override

public void run() {

while (true){

if (ticket>0){

System.out.println(Thread.currentThread().getName()+":卖出票号"+ticket);

ticket--;

// 睡眠100毫秒凸显问题

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}else {

break;

}

}

}

}

出现的问题,运行时,会出现重票,错票的问题,可以明显看到下图,出现很多重票,同时很多票号也不见了,例如11号票

106877f855c4

image.png

解决方案

synchronized关键字之-同步代码块

同步代码快之类锁方式实现线程安全:使用synchronized包裹if-else块,如果直接锁住while循环,会导致第一个进去的线程一直抢占cpu资源,虽然票号正确,但是所有票都是同一个窗口卖出

class RunnableWindow implements Runnable {

private int ticket = 100;

@Override

public void run() {

while (true) {

// 新加行,synchronized (RunnableWindow.class)表示锁住当前类,synchronized (this)指代当前类的实例对象

//synchronized (this){

synchronized (RunnableWindow.class) {

if (ticket > 0) {

System.out.println(Thread.currentThread().getName() + ":卖出票号" + ticket);

ticket--;

// 睡眠100毫秒凸显问题

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

} else {

break;

}

}

}

}

}

同步代码块之对象锁方式实现线程安全

class RunnableWindow implements Runnable {

private int ticket = 100;

// 新加行,创建一个object对象

private Object obj = new Object();

@Override

public void run() {

while (true) {

// 新加行,使用对象来锁住当前代码块

synchronized (obj) {

if (ticket > 0) {

System.out.println(Thread.currentThread().getName() + ":卖出票号" + ticket);

ticket--;

// 睡眠100毫秒凸显问题

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

} else {

break;

}

}

}

}

}

synchronized关键字之-同步方法

同步方法之对象锁方式实现线程安全:synchronized关键字修饰的非静态方法,表示当锁为当前类对象实例,如果修饰的为静态方法,则表示锁为当前类,为类锁

class RunnableWindow implements Runnable {

private int ticket = 100;

@Override

public void run() {

while (true) {

// 新加行调用同步方法

getTicket();

// 循环判断票数是否小于等于0,是则跳出循环

if (ticket<=0){

break;

}

}

}

// synchronized关键字修饰方法,实现同步方法

private synchronized void getTicket(){

if (ticket > 0) {

System.out.println(Thread.currentThread().getName() + ":卖出票号" + ticket);

ticket--;

// 睡眠100毫秒凸显问题

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

Lock锁方式:lock()与unlock()方法之间的代码为同步代码块,每次只允许一个线程进入

class RunnableWindow implements Runnable {

private int ticket = 100;

// 新建一个ReentrantLock实例

private ReentrantLock lock = new ReentrantLock();

@Override

public void run() {

while (true) {

try {

// 新加行

lock.lock();

if (ticket > 0) {

System.out.println(Thread.currentThread().getName() + ":卖出票号" + ticket);

ticket--;

// 睡眠100毫秒凸显问题

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

} else {

break;

}

} finally {

// 新加行

lock.unlock();

}

}

}

}

106877f855c4

image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值