Java—多线程安全解决方案

本文探讨了Java中多线程环境下线程安全问题的根源,并介绍了三种解决方法:使用synchronized关键字创建同步代码块或同步方法,以及利用Lock锁进行资源访问控制,确保在并发场景下数据的一致性和完整性。

   学习过操作系统原理同学们都知道,当多个线程或者进程访问共享数据,也就是说临界资源的时候会导致程序的可再现性失效。  在程序中,多线程同时运行相同代码块,也就是说多个线程对全局变量,静态变量进行写操作的时候,都会产生安全问题。

  还记的当初我们是如何解决线程该类问题的吗?同步机制,整型信号量机制,信号量机制,以及AND型信号量机制,是否想起PV操作?

例子:电影院今天卖电影票100张,三个窗口都卖,会出现怎样的结果呢?

public class DemoRunnable implements  Runnable {
    public int ticket=100;
    @Override
    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 MIanRunnable {
    public static void main(String[] args){
        //创建Runnable接口实现类对象
        DemoRunnable r=new DemoRunnable();
        //创建Thread对象,构造方法中传递Runnable接口实现类对象
        Thread t0=new Thread(r,"0号窗口");
        Thread t1=new Thread(r,"1号窗口");
        Thread t2=new Thread(r,"2号窗口");
       //调用start()方法开始多线程
        t0.start();
        t1.start();
        t2.start();
    }
}


个别结果:
2号窗口→正在卖第1票
1号窗口→正在卖第0票
0号窗口→正在卖第-1票
0号窗口→正在卖第22票
2号窗口→正在卖第22票
1号窗口→正在卖第22票

通过结果我们发现,不同的窗口可以卖重复票,以及可以卖负票。显然是不符合常理的。这就是线程安全问题,多个线程访问同一个资源的时候,且这多个线程对资源进行写操作的时候,就会出现线程安全问题。

    出现问题的原因,多个线程,同时对同一资源(此处指全局变量ticket)进行写操作,所以任意一个时刻,只能有一个线程对资源进行访问,才能解决该类问题。

①同步代码块:synchronized 关键字,用于方法中某一块代码,表示该块代码的资源实行互斥访问。

//全局变量共享票
    public int ticket = 100;
    //创建一个锁对象
    Object obj = new Object();
    @Override
    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--;
                }
            }
        }
    }
}

②同步方法,用synchronized关键字修饰的方法,某一线程执行该方法,其他线程处于阻塞态

public class synchronize implements Runnable {
    //共享票
    public int ticket = 100;

    @Override
    public void run() {

        Ticket();
    }

    public synchronized void Ticket(){
        //循环卖票过程
        while (true) {
            //同步代码块
            //判断是否还有票
            if (ticket > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() +
                        "→正在卖第" + ticket + "张票");
                ticket--;
            }
        }
    }
}

③Lock锁,也可以叫做同步锁,存在加同步锁和释放同步锁的方法

public class lock implements Runnable {
    //共享票
    public int ticket = 100;
   //成员位置创建一个ReetrantLock锁
    Lock l=new ReentrantLock();

    @Override
    public void run() {
        Ticket();
    }

    public synchronized void Ticket(){
        //循环卖票过程
        while (true) {
            //在可能出现问题的代码前调用LOck接口中的方法Lock获取锁
            l.lock();
            //判断是否还有票
            if (ticket > 0) {
                try {
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName() +
                            "→正在卖第" + ticket + "张票");
                    ticket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally {
                    //无论程序异常都会释放锁
                    //在可能出现问题的代码后调用LOck接口中的方法unLock获取锁
                    l.unlock();
                }

            }
        }
    }
}

关于Java多线程解决方案,就先分享到这里,内容不是很详细,但是很实用,有待完善!

评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值