先看懂一段代码:
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
我们先来回忆一下同步的前提:
- 必须要有两个或者两个以上的线程
- 必须是多个线程使用同一个锁
很明显我们代码满足第一个条件,所以应该是第二个前提上出了问题,于是我们回看代码发现,第一个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
更多有关锁的问题,可移步至”对象锁,方法锁,类锁区别总结“