Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

一、当两个并发线程访问同一个对象object的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行(如果多个线程调用同一个线程,只能有一个线程得到执行)另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞

五、以上规则对其它对象锁同样适用.

举例说明:  
 一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

package ths;
public class Thread1 implements Runnable {  public void run() {  synchronized(this) {  for (int i = 0; i < 5; i++) {  System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);  }  }  }  public static void main(String[] args) {  Thread1 t1 = new Thread1();  Thread ta = new Thread(t1, "A");  Thread tb = new Thread(t1, "B");  ta.start();  tb.start();  }
}

结果:

    A synchronized loop 0  A synchronized loop 1  A synchronized loop 2  A synchronized loop 3  A synchronized loop 4  B synchronized loop 0  B synchronized loop 1  B synchronized loop 2  B synchronized loop 3  B synchronized loop 4

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

package ths;
public class Thread2 {  public void m4t1() {  synchronized(this) {  int i = 5;  while( i-- > 0) {  System.out.println(Thread.currentThread().getName() + " : " + i);  try {  Thread.sleep(500);  } catch (InterruptedException ie) {  }  }  }  }  public void m4t2() {  int i = 5;  while( i-- > 0) {  System.out.println(Thread.currentThread().getName() + " : " + i);  try {  Thread.sleep(500);  } catch (InterruptedException ie) {  }  }  }  public static void main(String[] args) {  final Thread2 myt2 = new Thread2();  Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  );  Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  );  t1.start();  t2.start();  }
}

结果:

    t1 : 4  t2 : 4  t1 : 3  t2 : 3  t1 : 2  t2 : 2  t1 : 1  t2 : 1  t1 : 0  t2 : 0

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

//修改Thread2.m4t2()方法:

 public void m4t2() {  synchronized(this) {  int i = 5;  while( i-- > 0) {  System.out.println(Thread.currentThread().getName() + " : " + i);  try {  Thread.sleep(500);  } catch (InterruptedException ie) {  }  }  }}

结果:

   t1 : 4  t1 : 3  t1 : 2  t1 : 1  t1 : 0  t2 : 4  t2 : 3  t2 : 2  t2 : 1  t2 : 0

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

//修改Thread2.m4t2()方法如下:

 public synchronized void m4t2() {  int i = 5;  while( i-- > 0) {  System.out.println(Thread.currentThread().getName() + " : " + i);  try {  Thread.sleep(500);  } catch (InterruptedException ie) {  }  }  }

结果:

  t1 : 4  t1 : 3  t1 : 2  t1 : 1  t1 : 0  t2 : 4  t2 : 3  t2 : 2  t2 : 1  t2 : 0

五、以上规则对其它对象锁同样适用:

package ths;public class Thread3 { class Inner { private void m4t1() { int i = 5; while(i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i); try { Thread.sleep(500); } catch(InterruptedException ie) { } } } private void m4t2() { int i = 5; while(i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); try { Thread.sleep(500); } catch(InterruptedException ie) { } } } } private void m4t1(Inner inner) { synchronized(inner) { //使用对象锁
          inner.m4t1(); } private void m4t2(Inner inner) { inner.m4t2(); } public static void main(String[] args) { final Thread3 myt3 = new Thread3(); final Inner inner = myt3.new Inner(); Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1"); Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2"); t1.start(); t2.start(); }
}

结果:

尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰

  t1 : Inner.m4t1()=4  t2 : Inner.m4t2()=4  t1 : Inner.m4t1()=3  t2 : Inner.m4t2()=3  t1 : Inner.m4t1()=2  t2 : Inner.m4t2()=2  t1 : Inner.m4t1()=1  t2 : Inner.m4t2()=1  t1 : Inner.m4t1()=0  t2 : Inner.m4t2()=0

现在在Inner.m4t2()前面加上synchronized:

 private synchronized void m4t2() {  int i = 5;  while(i-- > 0) {  System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);  try {  Thread.sleep(500);  } catch(InterruptedException ie) {  }  }  }

结果:

尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。

 t1 : Inner.m4t1()=4  t1 : Inner.m4t1()=3  t1 : Inner.m4t1()=2  t1 : Inner.m4t1()=1  t1 : Inner.m4t1()=0  t2 : Inner.m4t2()=4  t2 : Inner.m4t2()=3  t2 : Inner.m4t2()=2  t2 : Inner.m4t2()=1  t2 : Inner.m4t2()=0

转载于:https://www.cnblogs.com/alsf/p/6786519.html

java线程同步: synchronized详解(转)相关推荐

  1. java 线程同步的list_java集合框架线程同步代码详解

    List接口的大小可变数组的实现.实现了所有可选列表操作,并允许包括null在内的所有元素.除了实现List接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小.(此类大致上等同于Vector ...

  2. Java线程池ThreadPool详解

    Java线程池ThreadPool详解 1. 线程池概述 1.1 线程池简介 1.2 线程池特点 1.3 线程池解决问题 2. 线程池原理分析 2.1 线程池总体设计 2.6 线程池流转状态 2.2 ...

  3. Java 线程同步 synchronized

    先来看一个不带线程同步的例子,这个例子很简单,只是让两个线程输出同样的内容,并不做其他的事,所以,线程同步在这里体现的并不明显. import java.util.Date;public class ...

  4. java线程池使用详解

    http://automaticthoughts.iteye.com/blog/1612388 一 简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使 ...

  5. java线程池使用详解ThreadPoolExecutor使用示例

    一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 1) 任务(Runnable /Callable) 2) 任务的执行(Exec ...

  6. Java线程池参数详解

    1:前言 在使用线程池时,为了获取最佳的性能,常常需要手动指定线程池的参数,ThreadPoolExecutor是最常用的线程池执行器,它有四个构造方法,参数最多的构造方法有7个参数,下面将详细介绍这 ...

  7. Java线程池(Executor)详解和用法

    背景 面试的时候经常会被三连问.用过吗?如何用的?场景是什么?所以有必要好好的研究下线程池迫在眉睫. 1.讲解之前先了解下 retry: 因为源码中有这个retry标记 先看一个简单的例子 /*** ...

  8. java 多线程同步_详解Java多线程编程中的线程同步方法

    1.多线程的同步: 1.1.同步机制:在多线程中,可能有多个线程试图访问一个有限的资源,必须预防这种情况的发生.所以引入了同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,直 ...

  9. java线程同步(synchronized,wait,notify,notifyAll)

    synchronized: 包括synchronized方法和synchronized块. synchronized方法使用this作为默认的"同步监视器",而synchroniz ...

  10. Java并发编程synchronized详解

    一.关于临界区.临界资源.竞态条件和解决方法 首先看如下代码,thread1对变量i++做500次运算,thread2对i--做500次运算,但是最终的结果却可能为是正数,负数,0不一样的结果. pa ...

最新文章

  1. 下载软件一直转圈圈_来了来了,百度网盘不限速!亲测满速,支持免登录下载!...
  2. oracle查找异常中断的sqlid方法,Oracle查找锁定对象以及强制解除锁定的方法
  3. c语言 error 9,C语言求助(_) c:9: error: syntax error before '[' token
  4. api接口怎么用_API接口的使用我这里用java和python都写出来了
  5. SVN工作笔记006---解决TortoiseSVN中out of date问题的一个方法
  6. Python标准库中的zipfile
  7. Python数据结构与算法笔记(七):数据结构——队列,链表和哈希表
  8. 二维 稳态边界层问题MATLAB,第三章 边界层理论.ppt
  9. vocabulary
  10. c语言编译defined,#if defined(__GNUC__)的意思是不是如果使用的是GCC编译器?
  11. 群晖服务器共享文件忘记密码,群晖NAS忘记登录的账号密码怎么办?
  12. 值得重视的网络安全问题
  13. matlab单双极性眼图程序,求通信大神讲讲这个matlab程序每一段的意思
  14. 2019,推荐几个牛逼大佬的公号
  15. 跨区域机房集中监控数据云平台运维管理方案
  16. layui下拉选择框开启搜索功能后,文本框会将Nbsp显示出来的解决办法
  17. 日本大型移动支付软件 PayPay 的 TiDB 迁移实践
  18. 查询任何一门课程成绩在70分以上的姓名、课程名称和分数
  19. C加加入门教程 1.什么是C加加?
  20. 【Envi】基于单窗算法的地表温度反演实验操作记录

热门文章

  1. 二维字符数组转字符串c语言,[求助] 怎样转换一个字符二维数组到一维数组~~~...
  2. python的menu_Python Tkinter Menu使用教程 | 學步園
  3. html中展开的小箭头,HTML5 移动网页应用中的展开式标签(带上下指示箭头)
  4. linux 查看系统位数命令,怎么用命令行查看Linux系统位数
  5. ef core 批量update 非id_Entity Framework (EF) Core
  6. minio获取上传文件_Springboot集成Minio实现对象存储服务
  7. [渝粤教育] 金陵科技学院 面向对象程序设计 参考 资料
  8. 【渝粤教育】国家开放大学2018年春季 0554-22T立体构成(一) 参考试题
  9. 【渝粤教育】10763k2_客户服务管理_21秋考试
  10. python--自己实现的单链表常用功能