synchronized同步语句块
用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个长时间的任务,那么B线程则必须等待比较长时间。在这样的情况下可以使用synchronized同步语句块来解决。
1、synchronized方法的弊端
为了证明synchronized关键字声明方法是有弊端的,看下图示例
package mytask;
import commonutils.CommonUtils;
public class Task {
private String getData1;
private String getData2;
public synchronized void doLongTimeTask() {
try {
System.out.println("begin task");
Thread.sleep(3000);
getData1 = "长时间处理任务后从远程返回的值1 threadName="
+ Thread.currentThread().getName();
getData2 = "长时间处理任务后从远程返回的值2 threadName="
+ Thread.currentThread().getName();
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package commonutils;
public class CommonUtils {
public static long beginTime1;
public static long endTime1;
public static long beginTime2;
public static long endTime2;
}
package mythread;
import commonutils.CommonUtils;
import mytask.Task;
public class MyThread1 extends Thread {
private Task task;
public MyThread1(Task task) {
super();
this.task = task;
}
@Override
public void run() {
super.run();
CommonUtils.beginTime1 = System.currentTimeMillis();
task.doLongTimeTask();
CommonUtils.endTime1 = System.currentTimeMillis();
}
}
package mythread;
import commonutils.CommonUtils;
import mytask.Task;
public class MyThread2 extends Thread {
private Task task;
public MyThread2(Task task) {
super();
this.task = task;
}
@Override
public void run() {
super.run();
CommonUtils.beginTime2 = System.currentTimeMillis();
task.doLongTimeTask();
CommonUtils.endTime2 = System.currentTimeMillis();
}
}
package test; import mytask.Task;
import mythread.MyThread1;
import mythread.MyThread2; import commonutils.CommonUtils; public class Run { public static void main(String[] args) {
Task task = new Task(); MyThread1 thread1 = new MyThread1(task);
thread1.start(); MyThread2 thread2 = new MyThread2(task);
thread2.start(); try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} long beginTime = CommonUtils.beginTime1;
if (CommonUtils.beginTime2 < CommonUtils.beginTime1) {
beginTime = CommonUtils.beginTime2;
} long endTime = CommonUtils.endTime1;
if (CommonUtils.endTime2 > CommonUtils.endTime1) {
endTime = CommonUtils.endTime2;
} System.out.println("耗时" + ((endTime - beginTime) / 1000));
}
}
结果:
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-0
长时间处理任务后从远程返回的值2 threadName=Thread-0
end task
begin task
长时间处理任务后从远程返回的值1 threadName=Thread-1
长时间处理任务后从远程返回的值2 threadName=Thread-1
end task
耗时:6
2、synchronized同步代码块的使用
当两个并发线程访问同一个对象ibject中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个代码块后才能执行该代码块。
package service;
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();
}
}
}
package extthread;
import service.ObjectService;
public class ThreadA extends Thread {
private ObjectService service;
public ThreadA(ObjectService service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
service.serviceMethod();
}
}
package extthread;
import service.ObjectService;
public class ThreadB extends Thread {
private ObjectService service;
public ThreadB(ObjectService service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
service.serviceMethod();
}
}
package test.run; import service.ObjectService;
import extthread.ThreadA;
import extthread.ThreadB; 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 =1403579513572
end end 1403579515572
begin time = 1403579515572
end end =1403579517572
这里虽然使用了synchronized同步代码块,但执行的效率还是没有提高
package mytask;
public class Task {
private String getData1;
private String getData2;
public void doLongTimeTask() {
try {
System.out.println("begin task");
Thread.sleep(3000);
String privateGetData1 = "长时间处理任务后从远程返回的值 1 threadName="
+ Thread.currentThread().getName();
String privateGetData2 = "长时间处理任务后从远程返回的值2 threadName="
+ Thread.currentThread().getName();
synchronized (this) {
getData1 = privateGetData1;
getData2 = privateGetData2;
}
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
begin task
begin task
长时间处理任务后远程返回的值1 threadName=Thread-1
长时间处理任务后远程返回的值2 threadName=Thread-0
end task
长时间处理任务后远程返回的值1 threadName=Thread-0
长时间处理任务后远程返回的值2 threadName=Thread-0
end task
耗时:3
通过上述可以看到,当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。
4、一半同步,一半异步
不在synchronized块中就是异步执行,在synchronized块中就是同步执行。
package mytask;
public class Task {
public void doLongTimeTask() {
for (int i = 0; i < 100; i++) {
System.out.println("nosynchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
System.out.println("");
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println("synchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
}
}
}
package mythread;
import mytask.Task;
public class MyThread1 extends Thread {
private Task task;
public MyThread1(Task task) {
super();
this.task = task;
}
@Override
public void run() {
super.run();
task.doLongTimeTask();
}
}
package mythread;
import mytask.Task;
public class MyThread2 extends Thread {
private Task task;
public MyThread2(Task task) {
super();
this.task = task;
}
@Override
public void run() {
super.run();
task.doLongTimeTask();
}
}
package test; import mytask.Task;
import mythread.MyThread1;
import mythread.MyThread2; public class Run { public static void main(String[] args) {
Task task = new Task(); MyThread1 thread1 = new MyThread1(task);
thread1.start(); MyThread2 thread2 = new MyThread2(task);
thread2.start();
}
}
如果非同步的时候会成为交叉打印,同步的话即还排队执行 。
5、synchronized代码块间的同步性
在使用synchronized(this)代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问被阻塞,这说明synchronized使用的"对象监视器"是一个。
package doubleSynBlockOneTwo; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ObjectService {
public void serviceMethodA(){
try {
synchronized (this) {
System.out.println("A begin time = " + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("A end time = " + System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} public void serviceMethodB(){
synchronized (this){
System.out.println("B begin time ="+System.currentTimeMillis());
System.out.println("B end time" + System.currentTimeMillis());
}
}
}
package doubleSynBlockOneTwo; import selfThread.ThreadB; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadA extends Thread { private ObjectService service;
public ThreadA(ObjectService service){
super();
this.service=service;
}
public void run(){
super.run();
service.serviceMethodA();
}
}
package doubleSynBlockOneTwo; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class ThreadB extends Thread { private ObjectService service;
public ThreadB(ObjectService service){
super();
this.service=service;
} public void run (){
super.run();
service.serviceMethodB();
}
}
package doubleSynBlockOneTwo; /**
* Created by Administrator on 2017/1/19 0019.
*/
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();
}
}
A begin time = 1484798392966
A end time = 1484798394978
B begin time =1484798394978
B end time1484798394978
6、同步synchronized(this)代码块是锁定当前对象的
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class Task {
public void otherMethod(){
System.out.println("---------------------------------run--otherMethod");
} public void doLongTimeTask(){
synchronized (this){
for (int i=0;i<100;i++){
System.out.println("synchronized threadName="+Thread.currentThread().getName()+"i="+(i+1));
}
}
}
}
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class MyThread1 extends Thread {
private Task task;
public MyThread1(Task task){
super();
this.task=task;
}
public void run(){
super.run();
task.doLongTimeTask();
}
}
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class MyThread2 extends Thread { private Task task;
public MyThread2(Task task){
super();
this.task=task;
}
public void run(){
super.run();
task.doLongTimeTask();
}
}
package synchronizedthis; /**
* Created by Administrator on 2017/1/19 0019.
*/
public class Run {
public static void main(String [] args){
Task task = new Task();
MyThread1 thread1 = new MyThread1(task);
thread1.start();
MyThread2 thread2 = new MyThread2(task);
thread2.start(); }
}
synchronized threadName=Thread-0i=1
synchronized threadName=Thread-0i=2
synchronized threadName=Thread-0i=3
synchronized threadName=Thread-0i=4
synchronized threadName=Thread-0i=5
synchronized threadName=Thread-0i=6
synchronized threadName=Thread-0i=7
synchronized threadName=Thread-0i=8
synchronized threadName=Thread-0i=9
synchronized threadName=Thread-0i=10
synchronized threadName=Thread-1i=1
synchronized threadName=Thread-1i=2
synchronized threadName=Thread-1i=3
synchronized threadName=Thread-1i=4
synchronized threadName=Thread-1i=5
synchronized threadName=Thread-1i=6
synchronized threadName=Thread-1i=7
synchronized threadName=Thread-1i=8
synchronized threadName=Thread-1i=9
synchronized threadName=Thread-1i=10
synchronized同步语句块的更多相关文章
- java多线程(三)——锁机制synchronized(同步语句块)
用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解 ...
- java synchronized静态同步方法与非静态同步方法,同步语句块
摘自:http://topmanopensource.iteye.com/blog/1738178 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...
- java中的synchronized同步代码块和同步方法的区别
下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...
- 59、synchronized同步代码块
synchronized同步方法的问题 有些情况下,在方法上面加synchronized同步,会有性能问题.请看下面代码,来计算下两个线程执行的耗时: package com.sutaoyu.Thre ...
- 2.2synchronized同步语句块
使用synchronized虽然能够避免不同步的现象出现,但是也会出现弊端,比如代码执行时间过长,那么其他线程就必须等待该线程执行完毕释放锁之后才能拿到锁. 面对这种问题可以使用同步代码块来解决. 2 ...
- 线程同步 synchronized 同步代码块 同步方法 同步锁
一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...
- synchronized(){}同步代码块笔记(新手笔记,欢迎纠正)
/* 内容:同步代码块,目的是解决多线程中的安全问题.什么安全问题呢??就是在执行run方法时,假如线程-0刚刚获得执行权, *还没执行时,就挂那了,这时线程-1获得执行权,并进行执行,就有可能出现负 ...
- 线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁
一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测 ...
- synchronized同步代码块锁释放
今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637 问题线程的内容. &quo ...
随机推荐
- linux内核支持U-disk和U转串
配置内核 make menuconfig,选中device驱动 Device Drivers ---->USB support--->USB Serial Converter suppor ...
- shell命令之根据字符串查询文件对应行记录
显示xxx字符串对应的行数,并向前打印3行,向后打印2行,查找对应文件为filename.txt 命令:grep -n 'xxx' -A3 -B2 --color=auto filename.txt ...
- 利用JavaScript计算引擎进行字符串公式运算
1.通过js计算引擎计算(java自带) 2.计算公式除了支持基本的方法之外还支持简单js脚本分支计算 3.通过设定map传入参数 4.默认返回最后一个计算结果,如果需返回特定值,将变量补写在公式最后 ...
- Axel 快速下载
Axel 是一个轻量级下载程序,它和其他加速器一样,对同一个文件建立多个连接,每个连接下载单独的文件片段以更快地完成下载. Axel 支持 HTTP.HTTPS.FTP 和 FTPS 协议.它也可以使 ...
- 简单又好用的聊天室技术——WebSocket
现在,很多网站为了实现推送技术,所用的技术都是轮询.轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器.这种传统的模式带来很 ...
- 很开心! 纪念一下 ^_^ 考勤系统(weX5+echarts3.0+Baas )
- 从零开始,制定PHP学习计划
7月份学习计划1-15 搭建开发环境.做个小demo 增删改查.Mysql数据库16-30号 架构设计.服务器管理.版本控制 8月份正式入手项目jquery脚本学习Thinksns开源学习.核心业务学 ...
- web开发之微信公众号---微信公众好开发
--------------------------------------time:2015/11/5 ----------------------------------------------- ...
- Linux基础回想(1)——Linux系统概述
1. 什么是操作系统?它与硬件以及其它软件之间的关系是如何的? 操作系统是控制和管理计算机系统内各种硬件和软件资源.有效组织多道程序执行的系统软件(或程序集合),是用户和计算机之间的接口.详细的说: ...
- Uniprot 数据库-最常用的蛋白质数据库
Uniprot 数据库是收录信息最全面的蛋白质数据库,包含swissport, uniparc, TrEMBL 3个子数据库: 其中swiss-prot 是手工核对过的 ,非冗余, 有详细注释信息的蛋 ...