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+源代码

Java中介者设计模式

Java 设计模式之模板方法开发中应用

设计模式之 Java 中的单例模式(Singleton)

更多详情见请继续阅读下一页的精彩内容:

  • 1
  • 2
  • 下一页

相关内容