歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java synchronized 總結

在Java開發的時候經常會用到關鍵字synchronized來對代碼進行同步,在使用的過程中,對於synchronized確不是很熟悉,最近在看Spring源碼時,發現有不少地方都用到同步,因此,趁此機會,研究一下。

1. synchronized鎖的對象

Java中的每一個對象都可以作為鎖。

1)對於同步方法,鎖是當前實例對象。

2)對於靜態同步方法,鎖是當前對象的Class對象。因為在Java 虛擬機中一個類只能對應一個類對象,所以同時只允許一個線程執行同一個類中的靜態同步方法。

3)對於同步方法塊,鎖是Synchonized括號裡配置的對象。

下面我們將一一根據代碼來介紹這幾種鎖。

2. 同步實例方法

對於同步方法,鎖是當前實例對象。即在同一時刻只能有一個線程可以訪問該實例的同步方法。但是請注意,如果有多個實例對象,那麼不同示例之間不受影響,線程可以同時訪問不同示例的同步方法。看下面這段代碼:

package com.bj.chenfeic.concurrency;

/**
 * 同步測試,提供了用於同步的實例方法
 *
 * @author chenfei0801
 *
 */
public class Sync {

    public synchronized void testSync() {
        long id = Thread.currentThread().getId();
        System.out.println("線程:" + id + "進入同步塊");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("線程:" + id + "退出同步塊");
    }
}

 

package com.bj.chenfeic.concurrency;

/**
 *
 * @author chenfei0801
 *
 */
public class SyncTread implements Runnable {

    @Override
    public void run() {
        Sync sync = new Sync();
        sync.testSync();
    }

}

 

package com.bj.chenfeic.concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
 * @author chenfei0801
 *
 */
public class SyncTest {

    /**
    * @param args
    */
    public static void main(String[] args) {
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
        for(int i=0;i<3;i++) {
            newFixedThreadPool.execute(new SyncTread());
        }
        newFixedThreadPool.shutdown();
       
    }

}

 

執行結果:

線程:11進入同步塊
線程:13進入同步塊
線程:12進入同步塊
線程:13退出同步塊
線程:11退出同步塊
線程:12退出同步塊

      從執行結果中,我們可以看到testSync並沒有同步,synchronized沒有生效。這是因為在SyncTherd中每次都是new Sync();這樣synchronized其實是作用到不同的對象上去了,所以各個線程之間其實並沒有同步。

      按照如下修改SynsThread、SyncTest代碼,即可達到同步作用

package com.bj.chenfeic.concurrency;

/**
 *
 * @author chenfei0801
 *
 */
public class SyncTread implements Runnable {
    private Sync sync;
    public SyncTread(Sync sync) {
        this.sync = sync;
    }

    @Override
    public void run() {
        this.sync.testSync();
    }

}

 

package com.bj.chenfeic.concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 *
 * @author chenfei0801
 *
 */
public class SyncTest {

    /**
    * @param args
    */
    public static void main(String[] args) {
        Sync sync = new Sync();//只實例化一次
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 3; i++) {
            newFixedThreadPool.execute(new SyncTread(sync));
        }
        newFixedThreadPool.shutdown();

    }

}

執行結果

線程:11進入同步塊
線程:11退出同步塊
線程:12進入同步塊
線程:12退出同步塊
線程:13進入同步塊
線程:13退出同步塊

      從上面結果中可以看出,SyncThread中使用的是同一個對象,此時線程是互斥訪問testSync()方法的,即達到了同步的作用。

大話設計模式(帶目錄完整版) PDF+源代碼 http://www.linuxidc.com/Linux/2014-08/105152.htm

Java中介者設計模式 http://www.linuxidc.com/Linux/2014-07/104319.htm

Java 設計模式之模板方法開發中應用 http://www.linuxidc.com/Linux/2014-07/104318.htm

設計模式之 Java 中的單例模式(Singleton) http://www.linuxidc.com/Linux/2014-06/103542.htm

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-10/107579p2.htm

Copyright © Linux教程網 All Rights Reserved