【Java多线程】synchronized同步语句块
目录
1. synchronized方法的弊端
2. synchronized同步代码块的使用
3. 用同步代码块解决同步方法的弊端
4. synchronized代码块间的同步性
5. 同步synchronized(this)代码块是锁定当前对象的
6. 将任意对象作为监视器
7. 细化验证3个结论
synchronized方法是对当前对象进行加锁,而synchronized代码块是对某一个对象进行加锁。
1. synchronized方法的弊端
在使用synchronized关键字来声明方法的时,线程需要排队执行,运行时间较长。
2. synchronized同步代码块的使用
当两个并发线程访问同一个对象object中的synchronized(this)同步代码时,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
下面通过一个示例来说明synchronized同步代码块的使用:
(1) ObjectService.java
public class ObjectService {public void serviceMethod() {try {synchronized (this) {System.out.println("begin time=" + System.currentTimeMillis());Thread.sleep(2000);System.out.println("end end=" + System.currentTimeMillis());}} catch (InterruptedException e) {e.printStackTrace();}}}
(2) ThreadA.java
public class ThreadA extends Thread {private ObjectService service;public ThreadA(ObjectService service) {super();this.service = service;}@Overridepublic void run() {super.run();service.serviceMethod();}}
(3) ThreadB.java
public class ThreadB extends Thread {private ObjectService service;public ThreadB(ObjectService service) {super();this.service = service;}@Overridepublic void run() {super.run();service.serviceMethod();}}
(4) Run.java
public class Run {public static void main(String[] args) {ObjectService service = new ObjectService();ThreadA a = new ThreadA(service);a.setName("a");a.start();ThreadB b = new ThreadB(service);b.setName("b");b.start();}}
运行结果:
begin time=1633959635246
end end=1633959637258
begin time=1633959637258
end end=1633959639259
上面的实验中虽然使用了synchronized同步代码块,但执行的效率还是没有提高,执行的效果还是同步运行的。
3. 用同步代码块解决同步方法的弊端
通过一个例子来说明:
(1)CommonUtils.java
public class CommonUtils {public static long beginTime1;public static long endTime1;public static long beginTime2;public static long endTime2;
}
(2) Task.java
public class Task {private String getData1;private String getData2;public void doLongTimeTask() {try {System.out.println("begin task");Thread.sleep(3000);String privateGata1 = "长时间处理任务后从远程返回的值 1 threadName="+ Thread.currentThread().getName();String privateGata2 = "长时间处理任务后从远程返回的值 2 threadName="+ Thread.currentThread().getName();synchronized(this) {getData1 = privateGata1;getData2 = privateGata2;}System.out.println(getData1);System.out.println(getData2);System.out.println("end task");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
(3) MyThread1.java
public class MyThread1 extends Thread {private Task task;public MyThread1(Task task) {super();this.task = task;}@Overridepublic void run() {super.run();CommonUtils.beginTime1 = System.currentTimeMillis();task.doLongTimeTask();CommonUtils.endTime1 = System.currentTimeMillis();}}
(4) MyThread2.java
public class MyThread2 extends Thread {private Task task;public MyThread2(Task task) {super();this.task = task;}@Overridepublic void run() {super.run();CommonUtils.beginTime2 = System.currentTimeMillis();task.doLongTimeTask();CommonUtils.endTime2 = System.currentTimeMillis();}}
(5) Run.java
public class Run {public static void main(String[] args) {Task task = new Task();MyThread1 thread1 = new MyThread1(task);thread1.setName("A");thread1.start();MyThread2 thread2 = new MyThread2(task);thread2.setName("B");thread2.start();try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}long beginTime = Math.min(CommonUtils.beginTime1, CommonUtils.beginTime2);long endTime = Math.max(CommonUtils.endTime1, CommonUtils.endTime2);System.out.println("耗时:" + ((endTime - beginTime) / 1000));}
}
运行结果:
begin task
begin task
长时间处理任务后从远程返回的值 1 threadName=B
长时间处理任务后从远程返回的值 2 threadName=A
长时间处理任务后从远程返回的值 1 threadName=A
长时间处理任务后从远程返回的值 2 threadName=A
end task
end task
耗时:3
通过上面的实验可知,当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。
不在synchronized块中就是异步执行,在synchronized块中就是同步执行。
4. synchronized代码块间的同步性
在使用同步synchronized(this)代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程同时对一个object中所有其他synchronized(this)同步代码块的访问将阻塞,这说明synchronized使用的“对象监视器”是一个。
5. 同步synchronized(this)代码块是锁定当前对象的
和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的。
6. 将任意对象作为监视器
多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果就是按顺序执行,也就是同步的,阻塞的。
这说明synchronized同步方法或synchronized(this)同步代码块分别由两种作用。
(1)synchronized同步方法
- 1) 对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态。
- 2) 同一时间只有一个线程可以执行synchronized同步方法中的代码。
(2)synchronized(this)同步代码块
- 1) 对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态。
- 2) 同一时间只有一个线程可以执行synchronized(this)同步代码中的代码。
在前面的学习中,使用synchronized(this)格式来同步代码块,其实Java还支持对“任意对象”作为“对象监视器”来实现同步功能。这个“任意对象”大多数是实例变量及方法的参数,使用格式为synchronized(非this对象)。
根据前面对synchronized(this)同步代码块的作用总结可知,synchronized(非this对象)格式的作用只有一种,即 synchronized(非this对象x)同步代码块。
- 1) 在多个线程持有“对象监视器”为同一对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码。
- 2) 当持有“对象监视器”为同意对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象x)同步代码块中的代码。
使用synchronized(非this对象x)同步代码块格式进行同步操作时,对象监视器必须是同一个对象。如果不是同一个对象监视器,运行的结果就是异步调用了,就会交叉运行。
锁非this对象具有一定的优点:如果在一个类中有很多个synchronized方法,这这时虽然能实现同步,但会受到阻塞,所以影响运行效率;但如果使用同步代码块锁非this对象,则synchronized(非this)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,则可大大提高运行效率。
同步代码放在非同步synchronized方法中进行声明,并不能保证调用方法的线程的执行同步/顺序性,也就是线程调用方法的顺序是无序的,虽然在同步块中执行的顺序是同步的,这样极易出现“脏读”问题。
7. 细化验证3个结论
“synchronized(非this对象x)”格式的写法是将x对象本身作为“对象监视器”,这样就可以得出以下3个结论:
- 1)当多个线程同时执行synchronized(x){}同步代码块时呈同步效果。
- 2)当其他线程执行x对象中其他synchronized同步方法时呈同步效果。
- 3)当线程执行x对象方法里面的synchronized(this)代码块时也呈现同步效果。
但需要注意:如果其他线程调用不加synchronized关键字的方法时,还是异步调用。
【Java多线程】synchronized同步语句块相关推荐
- [转载] java synchronized静态同步方法与非静态同步方法,同步语句块
参考链接: Java中的静态方法与实例方法 java synchronized静态同步方法与非静态同步方法,同步语句块 并发编程 线程同步 静态方法锁 非静态方法锁 同步块 进行多线程编程,同步控制是 ...
- java实验多线程机制_使用Java多线程的同步机制编写应用程序 PDF 下载
使用Java多线程的同步机制编写应用程序 PDF 下载 本站整理下载: 相关截图: 主要内容: 一. 实验名称 使用Java多线程的同步机制编写应用程序 二. 实验目的及要求 1.理解并行/并发的概念 ...
- Java多线程的同步机制(synchronized)
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...
- Java多线程的同步机制:synchronized
如果程序是单线程的,就不必担心此线程在执行时被其他线程"打扰",就像在现实世界中,在一段时间内如果只能完成一件事情,不用担心做这件事情被其他事情打扰.但是,如果程序中同时使用多线程 ...
- Java多线程-synchronized关键字
进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程 Ja ...
- java多线程、同步、异步
1.多线程.并发.异步.并行: 多线程是对cpu剩余劳动力的压榨,是一种技术.想想web server 需要处理大量并发请求的场景,是你同时给A,B,C...打电话(你的思维在不断切换,如一边给女朋友 ...
- Java多线程与同步
文章目录 1. 多线程概述 1.1 多线程引入 1.2 多线程概述 1.2.1 什么是进程? 1.2.2 多进程有什么意义呢? 1.2.3 什么是线程? 1.2.4 多线程有什么意义呢? 1.2.5 ...
- java多线程的同步
http://www.blogjava.net/jadmin/archive/2010/03/18/360497.html 多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用 ...
- Java 多线程 线程同步
线程同步 1.发生在多个线程操作同一个资源 2.并发:同一个对象被多个线程同时操作 3.于是,就需要线程同步.线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等 ...
- 多线程与同步代码块详解
线程是程序执行的一条路径, 一个进程中可以包含多条线程.多线程并发执行可以提高程序的效率,可以同时完成多项工作,多线程并发执行的实质就是CPU在做着高速的切换.多线程的应用场景:红蜘蛛同时共享屏幕给多 ...
最新文章
- 微软小冰作词又作曲,网友:要出道的节奏吗?
- 表转换存储引擎的方法总结
- Swift初探 1 helloWord
- Mysql VARCHAR(X) vs TEXT
- 前端学习(1840):前端面试题之小程序入门
- [Leetcode][第206题][JAVA][反转一个单链表][递归][迭代]
- 标题在上边框中的html(fieldset标签)
- Dijkstra算法(c++版)
- 脑电波连接计算机游戏,脑电波也能“玩游戏”?这个“挑战杯”全国一等奖告诉你这都不是事儿...
- 解决js函数中,参数不能有默认值的方法
- mac大小写切换快捷键,程序猿向
- 什么是CRM?多角度解析CRM系统
- 加州大学欧文分校 计算机专业,加州大学欧文分校计算机专业申请条件(附案例)...
- vba 添加outlook 签名_如何在Outlook中使用宏发送邮件,并且使用已有签名?
- F 魏迟燕的自走棋(思维+贪心+并查集维护联通块/左部点配对边<=2的匈牙利)
- 如何同步化本地svn库到googlecode
- FFmpeg截图以及生成缩略图
- lepus 监控mysql_Lepus(天兔)监控MySQL部署
- 扫地机器人朋友圈文案_扫地机发朋友圈说说
- 企业如何通过迁移到云平台来减少开支