线程的同步与死锁

1、线程同步:当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。如果线程不同步,即在不同线程同时访问同一资源的过程中就会出现问题。

2、线程同步处理——关键是“锁”

使用synchronized关键字实现线程同步。在同步代码块中的代码每次仅允许一个线程执行。

利用同步代码块解决:

class MyThread implements Runnable {
    private int ticket = 5;
    @Override
    public void run() {
        while(true) {
            synchronized(this) { //每次仅允许一个线程进行访问,“同步对象”参数,一般都选用当前线程对象this
                if(this.ticket > 0) {
                    try {
                        Thread.sleep(100); //暂缓执行
                    }catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() +"," + this.ticket --);
                }else {
                    System.out.println("结束");
                    break;
                }
            }
        }
    }
}
public class Demo {
    public static void main(String[] args) throws Exception {
        MyThread mt = new MyThread() ;
        new Thread(mt, "线程A").start();
        new Thread(mt, "线程B").start();
        new Thread(mt, "线程C").start();
        
    }
}

加入同步处理之后,程序的整体性能有所下降。

利用同步方法解决:

class MyThread implements Runnable {
    private int ticket = 5;
    public synchronized boolean sale() {
        if(this.ticket > 0) {
            try {
                Thread.sleep(100); //暂缓执行
            }catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() +"," + this.ticket --);
            return true;
        }else {
            System.out.println("结束");
            return false;
        }
    }
    @Override
    public void run() {
        while(this.sale()) {
            ;
        }
    }
}

3、线程死锁

造成死锁的主要原因在于线程之间在互相等待,等待对方让出资源。若干个线程访问同一资源时一定要进行同步处理,而过多的同步会造成死锁。

5、利用Object类解决重复操作

死等:public final void wait​() throws InterruptedException

设置等待时间:public final void wait​(long timeout) throws InterruptedException

设置等待时间:public final void wait​(long timeout,int nanos) throws InterruptedException

唤醒第一个等待线程:public final void notify();

唤醒全部等待线程:public final void notifyAll();

4、【生产者与消费者模型】

// 生产者与消费者模型
//生产者
class Producer implements Runnable {
    private Message1 msg ;
    public Producer(Message1 msg) {
        this.msg = msg ;
    }
    @Override
    public void run() {
        for(int x = 0 ; x < 6 ; x ++) {
            if(x % 2 == 0) {
                this.msg.set("标题一","内容一");
            }else {
                this.msg.set("标题二","内容二");
            }
        }
    }    
}
// 消费者
class Consumer implements Runnable {
    private Message1 msg ;
    public Consumer(Message1 msg) {
        this.msg = msg ;
    }
    @Override
    public void run() {
        for(int x = 0 ; x < 5 ; x ++) {
            System.out.println(this.msg.get());
        }
    }
    
}
//将同步处理交由Message完成(生产和消费的对象)
class Message1 {
    private String title;
    private String content;
    private boolean flag = true ; //表示生产和消费的形式,flag=true,允许生产但是不允许消费,避免一次生产多次消费等状况
    
    //同步处理后多个线程不能同时访问同一资源,通俗来讲,生产者在生产第一个产品时(mag.title和msg.content),不允许开始生产第二个
    public synchronized void set(String title, String content) {
        if(!this.flag) { //无法进行生产,应该等待被消费
            try {
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.title = title ;
        //允许有休眠
        try {
            Thread.sleep(100);
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
        this.content = content ;
        this.flag = false ; //已经生产过了
        super.notify(); //唤醒一下等待的进程
    }
    public synchronized String get() {
        if(this.flag == true) { //还未生产,需要等待
            try {
                super.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(100);
        }catch(InterruptedException e) {
            e.printStackTrace();
        }
        try {
            return this.title + "-" + this.content ;
        }finally {
            this.flag = true ; //继续生产
            super.notify(); //唤醒等待线程
        }
    }
}
public class Pool {
    public static void main(String[] args) throws Exception {
        Message1 msg = new Message1() ;
        new Thread(new Producer(msg)).start(); //启动生产者线程
        new Thread(new Consumer(msg)).start(); //启动消费者延迟
    }
}

通过同步处理与解决重复操作,此时刚好是:生产一个完整产品消费一个完整产品

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值