在java多線程編程中,咱們須要對java對象中的資源進行同步管理,確保在同一時刻,只能由同一線程訪問類或者對象中的資源,這樣能夠防止因爲幾個線程共享同一資源致使不可知的後果。java
方法之一就是利用資源鎖(synchronized),廢話少說,先上例子編程
例子一多線程
public class S_1 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread_1().start();
}
}
}ide
class Thread_1 extends Thread{
@Override
public synchronized void run() {
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}this
例子二:線程
public class S_2 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread_2().start();
}
}
}
class Thread_2 extends Thread{
@Override
public void run(){
synchronized(this){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}
}
對象
例子三:繼承
public class S3 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
new Thread_3().start();
}
}
}
class Thread_3 extends Thread{
public synchronized static void show(){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
@Override
public void run(){
show();
}資源
}
同步
例子四:
public class S_4 {
public static void main(String[] args) {
for(int i=0;i<5;i++){
String lock = "lock";
new Thread_4(lock).start();
}
}
}
class Thread_4 extends Thread{
private String lock ;
public Thread_4(String lock){
this.lock = lock ;
}
@Override
public void run(){
synchronized(lock){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}
}
以上四個例子是用五個線程從0-99進行打印,他們都是按照前後順序從0-99進行打印的嗎?若是你的答案是按順序依次打印的話,那你就錯了,下邊我一一來說解下
例子一,沒有按照前後順序進行打印。咱們對run方法進行了加鎖,按理說是該按照前後順序進行打印的,可是爲何結果與咱們想象的不同呢?因爲咱們起五個線程的時候,咱們建立了五個Thread_1對象,這樣每一個線程都獲取了一個對象,每一個線程都獲取了本身對象中run方法的鎖,因此,這裏的資源鎖是沒有意義的,若是要讓這裏的鎖起做用,除非該Thread_1是單例模式的,這樣這些線程都共享一個對象,纔會按照前後順序獲取鎖
例子二,沒有按照前後順序進行打印。咱們對run方法中的一部分代碼進行了synchronized塊保護,也應該按照每一個線程依次打印,但爲何仍是沒有依次打印呢?因爲咱們synchronized(this)中的this在五個線程中是沒有共享的,五個線程中的this都不同,這樣至關於對五個對象進行資源塊進行保護,五個線程依然可以同時獲取synchronized(this)方法中的代碼執行的鎖
例子三,按照前後順序打印。這個例子能夠和例子一對應起來看,咱們是在show方法上加的鎖,而且show方法是static的,這樣這裏方法就是類方法,被因此對象共享的,當咱們起五個線程,這五個線程對show方法是共享的,並且該方法被加鎖了,當線程來訪問的時候,首先看這個方法是否被其餘線程使用,若是正在被其餘對象使用,對不起,你先等着,等下一個線程用完了,退出了的時候,線程池中輪到你的時候,你才能執行該方法
例子四,按照前後順序打印。這個例子能夠和例子四對應起來看,首先咱們來看下例子4,類Thread_4是一個繼承Thread的線程類,他有一個私有變量lock,在其run方法中,咱們用鎖塊對要打印的語句進行保護,咱們在啓動線程的時候,經過構造方法,給Thread_4的lock變量進行賦值,因爲咱們啓動的五個線程中,每一個Thread對象的lock變量的值都是同一個,即五個線程共享變量lock,因此要執行被synchronized方法鎖起來的語句,也必須得到相應的鎖纔可以執行,對比例子一種,this的值在每一個線程中不同的
最後總結
若是咱們想經過synchronized來修辭方法,來達到在同一時刻,該方法只能被同一線程訪問的話,有兩個條件
條件一:線程對象是一個單例類
條件二:synchronized修飾的方法是static的
若是咱們想經過synchronized方法來達到在同一時刻,被保護的語句塊只能被同一線程訪問,其條件是
synchronized方法中傳入的對象必須是共享的,即傳入的對象必須是同樣的
但願這篇博文對你有用,若是我對synchronized認識不到位的地方,請多多指教