一、多線程-同步函數的鎖是this
/*
同步函數用的是哪一個鎖呢?
函數需要被對象調用。那么函數都有一個所屬對象引用。就是this。
所以同步函數使用的鎖是this。
通過該程序進行驗證。
使用兩個線程來買票。
一個線程在同步代碼塊中。 這兩個的鎖不一樣
一個線程在同步函數中。
都在執行買票動作。
*/
class Ticket implements Runnable
{
private int tick = 100;
Object obj = new Object();
boolean flag = true;
public void run()
{
if(flag)
{
while(true)
{
synchronized(this) /*同步函數的鎖*/
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
}
}
}
}
else
while(true)
show(); /*使用this鎖*/
}
public synchronized void show()//this
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
}
}
}
class ThisLockDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag = false;
t2.start();
// Thread t3 = new Thread(t);
// Thread t4 = new Thread(t);
// t3.start();
// t4.start();
}
}
二、多線程-靜態同步函數的鎖是class對象
/*
如果同步函數被靜態修飾后,使用的鎖是什么呢?
通過驗證,發現不在是this。因為靜態方法中也不可以定義this。
靜態進內存是,內存中沒有本類對象,但是一定有該類對應的字節碼文件對象。
類名.class 該對象的類型是Class
靜態的同步方法,使用的鎖是該方法所在類的字節碼文件對象。 類名.class
*/
class Ticket implements Runnable
{
private static int tick = 100;
//Object obj = new Object();
boolean flag = true;
public void run()
{
if(flag)
{
while(true)
{
synchronized(Ticket.class) /*使用了靜態,鎖就變了*/
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
}
}
}
}
else
while(true)
show();
}
public static synchronized void show()
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
}
}
}
class StaticMethodDemo
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag = false;
t2.start();
}
}
三、多線程-單例設計模式-懶漢式 出現的安全問題
/*
單例設計模式。 必須要記住,面試題
餓漢式與懶漢式的區別
1.懶漢式是延時加載的形式
2.懶漢式由於是延時加載,所以在多線程中會出現安全問題
3.可以加同步函數或者同步代碼塊來解決,而同步函數每次都需要判斷比較慢
4.這里采用同步代碼塊來解決安全問題
5.由於函數是靜態的,所以鎖是類名.class
*/
//餓漢式。
/*
class Single
{
private static final Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
*/
//懶漢式
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
//--->A;
s = new Single();
}
}
return s;
}
}
class SingleDemo
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
四、死鎖(要避免出現和熟悉)
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
}
class MyLock
{
static Object locka = new Object(); /*靜態,能用類名直接調用*/
static Object lockb = new Object();
}
class DeadLockTest
{
public static void main(String[] args)
{
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
}
}