多线程就要涉及到同步问题,同步就要解决线程安全问题。
首先同步的前提是:有两个或以上线程,且用的是同一个锁。
同步的形式有:同步函数、同步代码块。
同步的好处是:解决线程安全问题。
同步的弊端是:每个都要访问锁,降低效率;且锁嵌套,容易造成死锁。
线程间通讯用等待唤醒机制解决安全问题。
死锁的原因是锁嵌套,A拿着A锁不放,要去拿B锁;B拿着B锁不放,要去拿A锁。导致线程都在等待中,无法继续执行。
class MyDLock
{
public static void main(String[] args)
{
//创建Thread对象,将自己的类对象传进去,调用start方法启动线程
new Thread(new MyTest(true)).start(); //执行if里的代码
new Thread(new MyTest(false)).start(); //执行else里的代码
}
}
//实现Runnable接口,避免单继承的局限性
class MyTest implements Runnable
{
private boolean flag;
//实例化对象时,传入标记
MyTest(boolean flag)
{ //this.flag表示调用本类对象中的属性
this.flag = flag;
}
//覆写run方法,将要同时运行的代码写在run里面
public void run()
{
if(flag)
{
//为了看到死锁情况,同步代码一直运行,总会出现死锁
while(true)
{
//同步代码块的锁可以是任意对象,这里用的是 MyDLock.class,即字节码文件对象
//同步函数的锁是this,静态同步函数的锁是 类名.clalss
synchronized(MyDLock.class)
{
//Thread.currentThread()获得当前线程对象,getName()获得线程的默认名字
System.out.println(Thread.currentThread().getName()+":......if...... locka ");
//里面再嵌套一个同步代码块,用的锁是另一个对象MyTest.class
synchronized(MyTest.class)
{
System.out.println(Thread.currentThread().getName()+":...if...lockb");
}
}
}
}
else
{
while(true)
{
//这里的第一个锁是MyTest.class
synchronized(MyTest.class)
{
System.out.println(Thread.currentThread().getName()+":------else------lockb");
//这里的第二个锁是MyDLock.class
synchronized(MyDLock.class)
{
System.out.println(Thread.currentThread().getName()+":---else--- locka");
}
}
}
}
}
}
每次运行结果可能不一样,要看谁能获取CPU执行权。
两个可能会出现的结果: