首页 > 编程语言 > 详细

Java多线程二:线程同步

时间:2021-07-17 10:55:26      阅读:21      评论:0      收藏:0      [点我收藏+]

一、线程的死锁问题

1、死锁

  (1)不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的向步资源,就形成了线程的死锁。

  (2)出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。

2、解决方法

  (1)专门的算法、原则。

  (2)尽量减少同步资源的定义

  (3)尽量避免嵌套同步

二、同步代码块

1、格式:  

2、说明:  

(1)操作共享数据的代码,及需要被同步的代码;

(2)共享数据,多个线程共同操作的变量;

(3)同步监视器,俗称锁,如何一个类的对象都可以充当锁。

3、要求:多个线程必须要公用同一把锁

4、例子:4个窗口拿100个号码

class TakeNumber_1 implements Runnable{
    private int number = 100;
    Object object=new Object();

    //2.实现类去实现Runnable中抽象方法run()
    @Override
    public void run() {
        while (true){
            synchronized (object) {
                if (number > 0) {
                    //设置0.1秒的睡眠等待
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "拿到号码:" + number);
                    number--;
                } else {
                    break;
                }
            }
        }
    }
}

public class Synchronization {
    public static void main(String[] args) {
        //3.创建实现类的对象
        TakeNumber_1 takeNumber_1 = new TakeNumber_1();
        //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
        Thread t1 = new Thread(takeNumber_1,"窗口一");
        Thread t2 = new Thread(takeNumber_1,"窗口二");
        Thread t3 = new Thread(takeNumber_1,"窗口三");
        Thread t4 = new Thread(takeNumber_1,"窗口四");
        //5.通过Thread类的对象调用start()
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}

三、同步方法

1、对于继承Thread类时,需要将同步方法设为静态即可
    private static synchronized void show()

2.例子:4个窗口拿100个号码

class TakeNumber01 implements Runnable{
    private int number = 100;

    //2.实现类去实现Runnable中抽象方法run()
    @Override
    public void run() {
        while (true) {
            show();
        }
    }
        private synchronized void show(){   //同步监视器:this
            if (number>0){
                //设置0.1秒的睡眠等待
                try{
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"拿到号码:"+number);
                number--;
            }
        }
}

public class TakeTest01 {
    public static void main(String[] args) {
        TakeNumber01 takeNumber01 = new TakeNumber01();
        Thread t1 = new Thread(takeNumber01,"窗口一");
        Thread t2 = new Thread(takeNumber01,"窗口二");
        Thread t3 = new Thread(takeNumber01,"窗口三");
        Thread t4 = new Thread(takeNumber01,"窗口四");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

四、Lock锁-----JDK5.0新增

1、Lock锁

(1)从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。

(2)java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。

(3)ReentrantLock类实现了Lock,它拥有与 synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。

2、例子:4个窗口拿100个号码

class Windo implements Runnable {
    private int number = 100;

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

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

                if (number > 0) {
                    //设置0.1秒的睡眠等待
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "拿到号码:" + number);
                    number--;
                }
            }finally {
                //3.调用解锁方法:unlock()
                lock.unlock();
            }
        }
    }

}

public class LockTest {
    public static void main(String[] args) {
        Windo w1 = new Windo();
        Thread t1 = new Thread(w1, "窗口一");
        Thread t2 = new Thread(w1, "窗口二");
        Thread t3 = new Thread(w1, "窗口三");
        t1.start();
        t2.start();
        t3.start();
    }
}

五、总结

1、Synchronized和lock的异同

(1)相同:二者都可以解决线程安全问题

(2)不同:synchronized机制在执行完相应的同步代码后,自动的释放同步监视器

                    lock需要手动的启动同步(lock())和结束同步(unlock())

2、sleep()和wait()的异同

(1)相同:一旦执行方法,都可以使当前的线程进入阻塞状态

(2)不同:

    1) 两个方法声明的位置不同:Thread类中声明sleep(),Object类中声明wait()

    2) 调用要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用在同步代码块或同步方法中

    3) 关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。

 

 

 
 

 

Java多线程二:线程同步

原文:https://www.cnblogs.com/NiShilin/p/15022350.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!