多线程中同步函数的对象锁是this原因分析

先看一段代码:

package test1;

class MyThread implements Runnable
{
    private int tick = 100;
    Object obj = new Object();
    boolean flag = true;
    public void run()
    {
        if(flag)
        {
            while(true)
            {
                synchronized (obj)          //第一个synchronized
                {
                    if (tick >0)
                    {
                        try
                        {
                            Thread.sleep(10);
                        }
                        catch (Exception e)
                        {

                        }
                        System.out.println(Thread.currentThread().getName()+"...code"+tick--);
                    }
                }
            }
        }
        else
        {
            while(true)
            {
                show();
            }
        }
    }
    public synchronized void show()        //第二个synchronized
    {
        if(tick > 0)
        {
            try{
                Thread.sleep(10);
            }
            catch (Exception e)
            {

            }
            System.out.println(Thread.currentThread().getName()+"...show......"+tick--);
        }
    }
}

class test {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t1.start();
        try
        {
            Thread.sleep(10);
        }
        catch (Exception e)
        {

        }
        t.flag = false;
        t2.start();

    }

}

运行结果如下:
在这里插入图片描述
这是截取的最后一小段代码,看似没有什么问题,但让我们再运行一次看看!!
在这里插入图片描述
看!!!此时就出问题了,因为竟然打印出了code 0,程序中是 if (tick>0) 才会输出tick的数值,这表明线程出现了安全问题!!但是代码里面不是写了synchronized的吗??而且还写了两个啊!!

没错,问题就是出在这里!写了两个synchronized

我们先来回忆一下同步的前提:

  1. 必须要有两个或者两个以上的线程
  2. 必须是多个线程使用同一个锁

很明显我们代码满足第一个条件,所以应该是第二个前提上出了问题,于是我们回看代码发现,第一个synchronized的对象锁是obj,那就是说明同步函数中synchronized的对象锁不是obj

那接下来我们就试着更改对象锁obj为this看是否能够解决这个问题:

package test1;

class MyThread implements Runnable
{
    private int tick = 100;
    boolean flag = true;
    public void run()
    {
        if(flag)
        {
            while(true)
            {
                synchronized (this)         //将obj更改为this
                {
                    if (tick >0)
                    {
                        try
                        {
                            Thread.sleep(10);
                        }
                        catch (Exception e)
                        {

                        }
                        System.out.println(Thread.currentThread().getName()+"...code"+tick--);
                    }
                }
            }
        }
        else
        {
            while(true)
            {
                show();
            }
        }
    }
    public synchronized void show()
    {
        if(tick > 0)
        {
            try{
                Thread.sleep(10);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"...show......"+tick--);
        }
    }
}

class test {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t1.start();
        try
        {
            Thread.sleep(10);
        }
        catch (Exception e)
        {

        }
        t.flag = false;
        t2.start();

    }

}

部分运行结果如下:

and
在这里插入图片描述
多次运行发现,都没有出现”Thread-1… show…0“ ,这说明解决了线程安全的问题,也证实了同步函数中的对象锁是this

更多有关锁的问题,可移步至”对象锁,方法锁,类锁区别总结“

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值