Java-线程的同步与死锁

一、同步问题

多线程在操作同一个资源时可能会带来信息的安全问题。可通过线程同步来解决。即在同一个时间段内,只能由一个线程进行,其他线程需在此线程执行完才能执行。添加同步有两种方式。同步后的操作效率低,但安全性高。

  1. 同步代码块:使用synchorized代码块,对当前待同步的对象进行包裹;
  2. 同步方法:定义public synchronized方法,在线程主方法中调用即可。

同步代码块

package com.joeaaa.demo12;
/*
* 同步代码块
*/
class MyThread1 implements Runnable{ // 线程主体类
    private int ticket = 6;

    @Override
    public void run() { // 线程主方法
        for(int x =0; x<10; x++){
            synchronized (this){
                if (this.ticket >0){
                    try{
                        Thread.sleep(100);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"卖票,ticket= "+ this.ticket--);
                }
            }
        }
    }
}
public class SynchonizedTest {
    public static void main(String[] args) {
        MyThread1 mt = new MyThread1();
        new Thread(mt,"票贩子A").start();
        new Thread(mt,"票贩子B").start();
        new Thread(mt,"票贩子C").start();
        new Thread(mt,"票贩子D").start();

    }
}
票贩子A卖票,ticket= 6
票贩子A卖票,ticket= 5
票贩子A卖票,ticket= 4
票贩子A卖票,ticket= 3
票贩子A卖票,ticket= 2
票贩子A卖票,ticket= 1

同步方法

package com.joeaaa.demo12;
/*
 * 同步方法
 */
class MyThread2 implements Runnable{
    private int ticket = 6;

    @Override
    public void run() {
        for(int x =0; x<10; x++){
            synchronized (this){
                this.saleTicket();
            }
        }
    }
    public synchronized void saleTicket(){ // 定义同步方法
        if (this.ticket >0){
            try{
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"卖票,ticket= "+ this.ticket--);
        }
    }
}
public class SynchronizedMethodTest {
    public static void main(String[] args) {
        MyThread2 mt = new MyThread2();
        new Thread(mt,"票贩子A").start();
        new Thread(mt,"票贩子B").start();
        new Thread(mt,"票贩子C").start();
        new Thread(mt,"票贩子D").start();

    }
}

二、死锁

多线程程序中会经常遇见。

Q:多线程操作同一资源时要考虑到哪些,会带来什么问题?
A :要考虑同步问题,过多的同步带来死锁。

解决数据的重复设置和重复取出:需要等待及唤醒机制

  1. 等待:public final void wait() throws InterruptedException;
  2. 唤醒第一个等待的线程:public final void notify(),按顺序唤醒;
  3. 唤醒全部等待线程:public final void notifyAll();

请解释sleep()和wait()的区别

  1. sleep()是Thread类定义的static方法,表示线程休眠,休眠到一定时间自动唤醒;
  2. wait()是Object类定义的方法,表示线程等待,一直等待到notify()或notifyAll()才结束等待。