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);
    }

    
}
复制代码

 

 

posted @   春天又来了  阅读(362)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示