zoukankan      html  css  js  c++  java
  • Java 线程的同步与死锁

    概念:Java同步和异步,阻塞和非阻塞

    1、线程的同步产生的原因

    没有同步的情况

    class MyThread1 implements Runnable
    {
        private int ticket=5;
        @Override
        public void run() {
            for(int x =0;x<20;x++)
            {
    
                if(ticket>0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket--);
                }
            }
        }
    
    }
    public class Test {
        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();
        }
    }
    
    票贩子C卖票:5
    票贩子D卖票:5
    票贩子B卖票:4
    票贩子A卖票:3
    票贩子D卖票:2
    票贩子C卖票:1
    票贩子A卖票:-1
    票贩子B卖票:0
    票贩子D卖票:-2
    

    可以看到又相同的票被卖了,还出现了负数票的情况。

    2、线程的同步处理操作

    实现同步的关键字synchronized,可以通过两种方式使用

    • 一种是同步代码块
    • 另外一种是同步方法
      在Java里面有四种代码块:普通代码块、构造块、静态块、同步块

    使用同步代码块实现同步

    class MyThread1 implements Runnable
    {
        private int ticket=10;
        @Override
        public void run() {
    
            for(int x =0;x<20;x++)
            {
                synchronized(this){
                    if(ticket>0) {
                        System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket--);
                    }
                }
            }
        }
    
    }
    public class SynchronizedThread {
        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卖票:10
    票贩子D卖票:9
    票贩子C卖票:8
    票贩子B卖票:7
    票贩子C卖票:6
    票贩子C卖票:5
    票贩子C卖票:4
    票贩子D卖票:3
    票贩子A卖票:2
    票贩子D卖票:1
    

    调用同步方法实现同步

    class MyThread1 implements Runnable
    {
        private int ticket=10;
        @Override
        public void run() {
            for(int x =0;x<20;x++)
            {
                this.sale();
            }
        }
        public  synchronized void sale()
        {
            if(ticket>0) {
                System.out.println(Thread.currentThread().getName()+"卖票:"+this.ticket--);
            }
        }
    
    }
    public class SynchronizedThread {
        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();
        }
    }
    

    3、线程的死锁情况

    Java 实例 - 死锁及解决方法
    死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。

    java 死锁产生的四个必要条件:
    1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
    2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
    3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
    4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

    解决方法:

    • 用信号量去控制死锁。
    • 调整申请锁的范围
    • 调整申请锁的顺序

    避免死锁:银行家算法。

    请解释多个线程访问统一资源时需要考虑哪些情况?有可能带来哪些后果?

    多个线程访问同一资源时要考虑到线程间的同步问题,可以使用同步代码或同步方法解决;
    同步代码块:synchronized(锁定对象){代码}
    同步方法: public synchronized 返回值 方法名称(){代码}
    但是过多的使用同步,有可能造成死锁。

    --------------- 我每一次回头,都感觉自己不够努力,所以我不再回头。 ---------------
  • 相关阅读:
    鼠标事件
    表单事件
    打印20行10列的星形矩形
    打印nn乘法表
    小芳的妈妈每天给她2.5元钱,她都会存起来,但是,每当这一天是存钱的第5天或者5的倍数的话,她都会花去6元钱,请问,经过多少天,小芳才可以存到100元钱。
    我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。请问,我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?
    匿名函数
    冒泡排序
    session --中间件
    对cookie-parser的理解(签名、加密)
  • 原文地址:https://www.cnblogs.com/zjw-blog/p/13649612.html
Copyright © 2011-2022 走看看