线程的同步

时间:2020-07-21 22:55:58   收藏:0   阅读:74

线程的同步

线程的安全问题

通过同步机制解决线程安全问题

方法一:同步代码块

格式

synchronized(同步监视器){

    需要被同步的代码

    }

举例说明

class Thread implements Runnable{

    private Object obj = new Object();

    public void run() {
        //使用类对象充当锁
        synchronized(obj){
        .......
        }
    }
}

说明

特点

代码实现

实现Runnable接口创建多线程的方式
/**
 * 创建三个窗口买票,票数100张:使用实现Runnable接口的方式实现的
 */
class WindowThread implements Runnable{

    private int ticket = 100;
    // private Object obj = new Object();

    public void run() {
        while (true) {
            //此时this:唯一的WindowThread对象
            synchronized(this){// 方式二:synchronized(obj){
                if (ticket > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread(). getName() + ":" + "买票,票号为" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }
        }
    }
}

public class Test1 {

    public static void main(String[] args) {
        WindowThread window = new WindowThread();

        Thread w1 = new Thread(window);
        Thread w2 = new Thread(window);
        Thread w3 = new Thread(window);

        w1.setName("窗口1");
        w1.start();
        w2.setName("窗口2");
        w2.start();
        w3.setName("窗口3");
        w3.start();
    }
}
继承Thread类创建多线程的方式
class Window extends Thread {
    // 大家公用数据,只有100张票
    private static int ticket = 100;
    private static Object obj = new Object();
    public void run() {
        while (true) {
            //方式二
            synchronized(Window.class){
                // 方式一:synchronized(obj){
                //synchronized(this)错误的,此时this代表着三个对象
                if(ticket > 0){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName() + ":" + "买票,票号为" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }

        }
    }
}

public class Test2 {
    public static void main(String[] args) {
        Window w1 = new Window();
        Window w2 = new Window();
        Window w3 = new Window();

        w1.setName("窗口1");
        w2.setName("窗口2");
        w3.setName("窗口3");

        w1.start();
        w2.start();
        w3.start();
    }
}

同步方法

如果操作共享数据的代码完整的声明在一个方法中,就可以将此方法声明同步的

格式

利用synchronized 修饰方法

public synchronized void XXX(){

}

public static synchronized void XXX(){

}

说明

代码实现

实现Runnable接口创建多线程的方式

非静态同步方法,调用this

class WindowThread3 implements Runnable{

    private int ticket = 100;
    private static boolean isFlag = true;
    // private Object obj = new Object();

    public void run() {
        while (isFlag) {
            show();
        }
    }

    public synchronized void show(){//同步监视器:this
        if (ticket > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread(). getName() + ":" + "买票,票号为" + ticket);
            ticket--;
        }else{
            isFlag = false;
        }
    }
}

public class Test3 {
    public static void main(String[] args) {
        WindowThread3 window = new WindowThread3();

        Thread w1 = new Thread(window);
        Thread w2 = new Thread(window);
        Thread w3 = new Thread(window);

        w1.setName("窗口1");
        w1.start();
        w2.setName("窗口2");
        w2.start();
        w3.setName("窗口3");
        w3.start();
    }
}
继承Thread类创建多线程的方式

静态同步方法,调用当前类本身

class Window4 extends Thread{
    private static int ticket = 100;
    private static boolean isFlag = true;

    @Override
    public void run() {
        while(isFlag){
            show();
        }
    }

    public static synchronized void show(){
        //同步监视器:Window.class
        if(ticket > 0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread(). getName() + ":" + "买票,票号为" + ticket);
            ticket--;
        }else{
            isFlag = false;
        }
    }
}

public class Test4 {
    public static void main(String[] args) {
        Window4 w1 = new Window4();
        Window4 w2 = new Window4();
        Window4 w3 = new Window4();

        w1.setName("窗口1");
        w2.setName("窗口2");
        w3.setName("窗口3");

        w1.start();
        w2.start();
        w3.start();
    }
}

通过Lock(锁)解决线程安全问题

步骤

  1. 实例化ReentrantLock

    private ReentrantLock lock = new ReentrantLock(true);

    • true代表公平
    • 不填默认为false
  2. 调用锁的方法

    lock.lock();

  3. 调用解锁的方法

    lock.unlock();

注意:其中调用lock()方法和unlock()方法时要用try()finally()包住
技术图片

代码实现

class Window5 implements Runnable {

    private int ticket = 100;

    //1.实例化ReentrantLock
    private ReentrantLock lock = new ReentrantLock(true);

    public void run() {
        while (true) {
            try{
                //2.调用锁定的方法:lock()
                lock.lock();

                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() +  "卖票" + ":" + "票号为" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }finally{
                //3.调用解锁的方法:unlock()
                lock.unlock();
            }
        }

    }

}

public class Test5 {
    public static void main(String[] args) {
        Window5 window = new Window5();

        Thread t1 = new Thread(window);
        Thread t2 = new Thread(window);
        Thread t3 = new Thread(window);

        t1.setName("窗口1:");
        t2.setName("窗口2:");
        t3.setName("窗口3:");

        t1.start();
        t2.start();
        t3.start();
    }
}

synchronized和Lock的异同

释放锁与不释放锁的操作

释放锁的操作

不释放锁的操作

使用顺序

Lock--->同步代码块--->同步方法

死锁

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!