zoukankan      html  css  js  c++  java
  • Java 简单了解线程 同步线程和死锁(二)

      例如上一篇的售票的例子,可能会打印出负数的票,主要的原因是由于线程之间的切换。要避免这个问题,必须在卖票的时候加一个限制,指定此时此刻只有等这个售票点卖完票,其他售票点才能卖票。

      看一下出现问题的情况

    public class test9 
    { 
        public static void main(String[] args)
        {
            TestThread t = new TestThread();
            new Thread(t).start();
            new Thread(t).start();
            new Thread(t).start();
            new Thread(t).start();
        }    
    }
    
    class TestThread implements Runnable
    {
            int tickets = 100;
            //String str = new String("");
        public void run()
        {
    
            while(true)
            {
    
                    if(tickets>0)
                    {
                        try{ Thread.sleep(10);}
                        catch(Exception e){}
                        System.out.println(Thread.currentThread().getName() + "当前票数还有:" + tickets--);
                    }
                
            }
        }
    }

      解决方法一,加一个synchronized关键字。给synchronized里传一个对象,他相当于一个标志位,当执行synchronized语句后此处变为0,他运行结束后又会变成1。当他是0的情况,那么其他线程运行到此处时会被阻塞

      

    public class test9 
    { 
        public static void main(String[] args)
        {
            TestThread t = new TestThread();
            new Thread(t).start();
            new Thread(t).start();
            new Thread(t).start();
            new Thread(t).start();
        }    
    }
    
    class TestThread implements Runnable
    {
        int tickets = 100;
        String str = new String("");
        public void run()
        {
    
            while(true)
            {
                synchronized(str)
                {
    
                    if(tickets>0)
                    {
                        try{ Thread.sleep(10);}
                        catch(Exception e){}
                        System.out.println(Thread.currentThread().getName() + "当前票数还有:" + tickets--);
                    }
                
                }
            }
        }
    }

      解决方法二,进一步的写法

    public class test9 
    { 
        public static void main(String[] args)
        {
            TestThread t = new TestThread();
            new Thread(t).start();
            new Thread(t).start();
            new Thread(t).start();
            new Thread(t).start();
        }    
    }
    
    class TestThread implements Runnable
    {
        int tickets = 100;
    //    String str = new String("");
        public void run()
        {
            while(true)
            {
                sale();
            }
        }
        
        public synchronized void sale()
        {
            if(tickets>0)
            {
                try{ Thread.sleep(10);}
                catch(Exception e){}
                System.out.println(Thread.currentThread().getName() + "当前票数还有:" + tickets--);
            }
        }
    }

      

      线程死锁原因:造成线程死锁一般的主要原因是出现的环路,你调用我,我调用你。彼此都在等待对方,出现无止境的等待。

      孙钟秀的操作系统教程里这么定义死锁:如果一个进程集合中的每个进程都在等待只能由此集合中的其他进程才能引发的事件,而无限期限入僵持的局面称为死锁。(省略其他一些文字,看黑色加粗部份会更好理解!)。虽然这个定义是对进程而言的,不对我想对线程同样适用。

      例如下面的程序

    View Code
    class A
    {
        synchronized void foo(B b)
        {
            String name = Thread.currentThread().getName();
            System.out.println(name + " entered A.foo ");
            
            Thread.sleep(1000):
    
            System.out.println(name + " trying to call B.last()");
            b.last();
        }
        synchronized void last()
        {
            //A.last
        }
    }
    
    class B
    {
        synchronized void bar(A a)
        {
            String name = Thread.currentThread().getName();
            System.out.println(name + " entered B.bast ");
            
            Thread.sleep(1000):
    
            System.out.println(name + " trying to call a.last()");
            a.last();
        }
    
        synchronized void last()
        {
            //B.last
        }    
    }
    
    
    class Deadlock implements Runnable
    {
        A a = new A();
        B b = new B();
        
        Deadlock()
        {
            new Thread(this).start();
            a.foo(b);        
        }
    
        public void run()
        {
            b.bar(a);
        }
    
        
    }
  • 相关阅读:
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 42. 连续子数组的最大和
    剑指 Offer 41. 数据流中的中位数
    剑指 Offer 40. 最小的k个数
    剑指 Offer 39. 数组中出现次数超过一半的数字
    剑指 Offer 38. 字符串的排列
    MySQL更改密码
    WPF中的MySQLHelper
    WPF多线程
    mysql-5.7.28-winx64(压缩包)安装教程
  • 原文地址:https://www.cnblogs.com/cxeye/p/2678194.html
Copyright © 2011-2022 走看看