线程与死锁(阿里云开发者社区)

文章介绍了在多线程环境中,由于并发访问共享资源可能导致的数据错误,通过一个简单的卖票程序展示了线程不同步的问题。然后,文章提出了使用`synchronized`关键字实现同步代码块或同步方法来解决线程安全问题,但同时指出同步可能会导致性能下降。此外,还提到了死锁的概念,即多个线程相互等待对方释放资源而形成的僵局。
摘要由CSDN通过智能技术生成

同步问题的引出

在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,于是当多个线程访问同一资源的时候如果处理不当就会产生数据的错误操作

下面编写一个简单的买票程序,将创建若干个线程对象实现卖票的处理操作.

public class MyThread6 implements Runnable{
    private int ticket  = 10;
    public void run(){
        while(true) {
            if (this.ticket > 0) {
                try {
                    Thread.sleep(1000); // 模拟网络延迟
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName() + "卖票\t ticket =" + this.ticket--);
            } else {
                System.out.println("*******票已经卖光了*****");
                break;
            }
        }
    }
}

 MyThread6 myt = new MyThread6();
        new Thread(myt,"售票厅1").start();
        new Thread(myt,"售票厅2").start();
        new Thread(myt,"售票厅3").start();

结果:
结果反映出了线程的不同步
这个问题就叫线程问题的不同步。

同步处理的解决方法

经过分析之后已经可以确定同步问题所产生的主要原因了,那么下面就需要进行同步问题的解决,但是解决同步问题的关键是锁,指的是当某一个线程执行操作的时候,其他线程外面等待。
如果要想在程序之中实现这把锁的功能,就可以使用synchronized关键字来实现,利用此关键字可以定义同步方法或者同步代码块,在同步代码块的操作里面的代码只允许一个线程执行

  1. 利用同步代码块进行处理
    synchronized(同步对象){
    同步代码操作
    }

一般要进行同步对象处理的时候可以采用当前对象this进行同步。

public class MyThread7 implements Runnable{
    private int ticket = 10;
    @Override
    public void run(){
        while (true){
            synchronized (this){
                if (this.ticket>0){
                    System.out.println(Thread.currentThread().getName()+"卖票\t ticket="+this.ticket--);
                }else {
                    System.out.println("-------票已经卖完了---------");
                    break;
                }
            }
        }
    }
}

        MyThread7 myt = new MyThread7();
        new Thread(myt,"售票厅1").start();
        new Thread(myt,"售票厅2").start();
        new Thread(myt,"售票厅3").start();

运行结果

加入同步处理之后,程序的整体的性能下降了。同步实际上会造成性能降低。
2. 在方法定义上使用synchronized关键字即可。

public class MyThread8 implements Runnable{
    private int ticket = 10;
    public synchronized boolean sale(){
        if (this.ticket>0){
            System.out.println(Thread.currentThread().getName()+"卖票\t ticket="+ticket--);
            return true;
        }else {
            System.out.println("票已经买完了");
            return false;
        }
    }
    @Override
    public void run(){
        while (this.sale()){
            
        };
    }
    
}

        MyThread8 myt = new MyThread8();
        new Thread(myt,"售票厅1").start();
        new Thread(myt,"售票厅2").start();
        new Thread(myt,"售票厅3").start();

运行结果
在日后学习Java类库的时候会发现,系统中许多的类上使用的同步处理采用的都是同步方法

同步会造成性能下降

死锁

死锁是在进行多线程同步的处理之中有可能产生的一种问题,所谓的死锁指的是若干个线程彼此互相等待的状态。下面通过一个简单的代码来观察一下死锁的表现形式,但是对于此代码不作为重点。


public class MyThread9 implements Runnable {
    private Jian jj = new Jian();
    private XiaoQiang xq= new XiaoQiang();
    @Override
    public void run(){
        jj.say(xq);
    }
    public void DeadLock(){
        new Thread(this).start();
        xq.say(jj);
    }
    public static void main(String args[]){
        new MyThread9();
    }
}
class Jian{
    public  synchronized void say(XiaoQiang xq){
        System.out.println("阿健说,此路是我开,要想从此过,留下10块钱");
    }
    public synchronized void get(){
        System.out.println("阿健说,得到了10块钱,可以买饭吃了,于是让出了路。");
    }
}
class XiaoQiang{
    public  synchronized void say(Jian jj){
        System.out.println("小强说,让我先跑,我再给你钱");
    }
    public  synchronized void get(Jian jj){
        System.out.println("小强说,逃过了一劫,可以继续送快餐了");
    }
}

现在死锁造成的主要原因是因为彼此都在互相等待着,等待着对方让出资源。死锁实际上是一种开发中出现的不确定的状态,有的时候代码如果处理不当则会不定期的处理死锁,这是属于正常开发中的调试问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值