转载自:http://blog.csdn.net/xiao__gui/article/details/8188833

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。synchronized既可以加在一段代码上,也可以加在方法上。

关键是,不要认为给方法或者代码段加上synchronized就万事大吉,看下面一段代码:

  1. class Sync {
  2. public synchronized void test() {
  3. System.out.println("test开始..");
  4. try {
  5. Thread.sleep(1000);
  6. } catch (InterruptedException e) {
  7. e.printStackTrace();
  8. }
  9. System.out.println("test结束..");
  10. }
  11. }
  12. class MyThread extends Thread {
  13. public void run() {
  14. Sync sync = new Sync();
  15. sync.test();
  16. }
  17. }
  18. public class Main {
  19. public static void main(String[] args) {
  20. for (int i = 0; i < 3; i++) {
  21. Thread thread = new MyThread();
  22. thread.start();
  23. }
  24. }
  25. }

运行结果:
test开始..
test开始..
test开始..
test结束..
test结束..
test结束..

可以看出来,上面的程序起了三个线程,同时运行Sync类中的test()方法,虽然test()方法加上了synchronized,但是还是同时运行起来,貌似synchronized没起作用。

将test()方法上的synchronized去掉,在方法内部加上synchronized(this):

  1. public void test() {
  2. synchronized(this){
  3. System.out.println("test开始..");
  4. try {
  5. Thread.sleep(1000);
  6. } catch (InterruptedException e) {
  7. e.printStackTrace();
  8. }
  9. System.out.println("test结束..");
  10. }
  11. }

运行结果:
test开始..
test开始..
test开始..
test结束..
test结束..
test结束..

一切还是这么平静,没有看到synchronized起到作用。

实际上,synchronized(this)以及非static的synchronized方法(至于static synchronized方法请往下看),只能防止多个线程同时执行同一个对象的同步代码段。

回到本文的题目上:synchronized锁住的是代码还是对象。答案是:synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this。

当synchronized锁住一个对象后,别的线程如果也想拿到这个对象的锁,就必须等待这个线程执行完成释放锁,才能再次给对象加锁,这样才达到线程同步的目的。即使两个不同的代码段,都要锁同一个对象,那么这两个代码段也不能在多线程环境下同时运行。

所以我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步。这叫减小锁的粒度,使代码更大程度的并发。原因是基于以上的思想,锁的代码段太长了,别的线程是不是要等很久,等的花儿都谢了。当然这段是题外话,与本文核心思想并无太大关联。

再看上面的代码,每个线程中都new了一个Sync类的对象,也就是产生了三个Sync对象,由于不是同一个对象,所以可以多线程同时运行synchronized方法或代码段。

为了验证上述的观点,修改一下代码,让三个线程使用同一个Sync的对象。

  1. class MyThread extends Thread {
  2. private Sync sync;
  3. public MyThread(Sync sync) {
  4. this.sync = sync;
  5. }
  6. public void run() {
  7. sync.test();
  8. }
  9. }
  10. public class Main {
  11. public static void main(String[] args) {
  12. Sync sync = new Sync();
  13. for (int i = 0; i < 3; i++) {
  14. Thread thread = new MyThread(sync);
  15. thread.start();
  16. }
  17. }
  18. }

运行结果:
test开始..
test结束..
test开始..
test结束..
test开始..
test结束..

可以看到,此时的synchronized就起了作用。

那么,如果真的想锁住这段代码,要怎么做?也就是,如果还是最开始的那段代码,每个线程new一个Sync对象,怎么才能让test方法不会被多线程执行。

解决也很简单,只要锁住同一个对象不就行了。例如,synchronized后的括号中锁同一个固定对象,这样就行了。这样是没问题,但是,比较多的做法是让synchronized锁这个类对应的Class对象。

  1. class Sync {
  2. public void test() {
  3. synchronized (Sync.class) {
  4. System.out.println("test开始..");
  5. try {
  6. Thread.sleep(1000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. System.out.println("test结束..");
  11. }
  12. }
  13. }
  14. class MyThread extends Thread {
  15. public void run() {
  16. Sync sync = new Sync();
  17. sync.test();
  18. }
  19. }
  20. public class Main {
  21. public static void main(String[] args) {
  22. for (int i = 0; i < 3; i++) {
  23. Thread thread = new MyThread();
  24. thread.start();
  25. }
  26. }
  27. }

运行结果:
test开始..
test结束..
test开始..
test结束..
test开始..
test结束..

上面代码用synchronized(Sync.class)实现了全局锁的效果。

最后说说static synchronized方法,static方法可以直接类名加方法名调用,方法中无法使用this,所以它锁的不是this,而是类的Class对象,所以,static synchronized方法也相当于全局锁,相当于锁住了代码段。

Java synchronized关键字的理解的更多相关文章

  1. Java Synchronized 关键字

    本文内容 Synchronized 关键字 示例 Synchronized 方法 内部锁(Intrinsic Locks)和 Synchronization 参考资料 下载 Demo Synchron ...

  2. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  3. [java] java synchronized 关键字详解

    Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一 ...

  4. Java synchronized关键字用法(清晰易懂)

    本篇随笔主要介绍 java 中 synchronized 关键字常用法,主要有以下四个方面: 1.实例方法同步 2.静态方法同步 3.实例方法中同步块 4.静态方法中同步块 我觉得在学习synchro ...

  5. java synchronized关键字浅探

    synchronized 是 java 多线程编程中用于使线程之间的操作串行化的关键字.这种措施类似于数据库中使用排他锁实现并发控制,但是有所不同的是,数据库中是对数据对象加锁,而 java 则是对将 ...

  6. java synchronized关键字

    引用其他人的一段话 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchro ...

  7. java synchronized关键字浅析

    synchronized这个关键字想必学Java的人都应该知道. 直接上例子: 方法级别实例 public class AtomicInteger { private int index; publi ...

  8. Java:synchronized关键字引出的多种锁

    前言 Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁.本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这 ...

  9. java synchronized关键字的底层实现

    每个对象都有一个锁(Monitor,监视器锁),class对象也有锁,如果synchronized关键字修饰同步代码块,通过反编译可以看到,其实是有个monitorenter和monitorexit指 ...

随机推荐

  1. Linux下类似windows下_beginthread和_endthread 的多线程开发

    在 windows下头文件中包含 #include<process.h> 就可以使用_beginthread进行线程创建.个人感觉挺方便的. 在linux下类似于_beginthread ...

  2. SOA和微服务到底是什么关系

    本文原创,原文地址为:http://www.cnblogs.com/fengzheng/p/5847441.html SOA和微服务到底是什么关系? 说实话,我确实不明白SOA和微服务到底有什么本质上 ...

  3. 趣味编程:静夜思(JOOL版)

    JOOL <dependency> <groupId>org.jooq</groupId> <artifactId>jool</artifactI ...

  4. Java8 Stream语法详解 2

    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...

  5. string类小结

    要想使用标准C++中string类,必须要包含 #include <string>// 注意是<string>,不是<string.h>,带.h的是C语言中的头文件 ...

  6. Hammer.js——给bootstrap添加触屏功能

    Hammer.js qq群号(html5技术交流):158677025   手机端演示二维码(或直接在手机中输入网址:http://lilinfeng.cncoder.me 浏览效果): 一.前言 移 ...

  7. Course Schedule课程表12(用Topological Sorting)

    [抄题]: 现在你总共有 n 门课需要选,记为 0 到 n - 1.一些课程在修之前需要先修另外的一些课程,比如要学习课程 0 你需要先学习课程 1 ,表示为[0,1]给定n门课以及他们的先决条件,判 ...

  8. OC 线程操作 - GCD队列组

    1.队列组两种使用方法2.队列组等待 wait /** 新方法 队列组一般用在在异步操作,在主线程写队列组毫无任何作用 */ - (void)GCD_Group_new_group___notify{ ...

  9. Python学习记录day8

    目录 Python学习记录day8 1. 静态方法 2. 类方法 3. 属性方法 4. 类的特殊成员方法 4.1 __doc__表示类的描述信息 4.2 __module__ 和 __class__ ...

  10. discuz模板引擎语法

    论坛的首页模板:forum/discuz.htm 版块的内容模板:forum/forumdisplay.htm 主题的查看模板:forum/viewthread.htm 帖子的内容模板:forum/p ...