用关键字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同步语句块的更多相关文章

  1. java多线程(三)——锁机制synchronized(同步语句块)

    用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法之行一个长时间的任务,那么B线程必须等待比较长的时间,在这样的情况下可以使用synchronized同步语句快来解 ...

  2. java synchronized静态同步方法与非静态同步方法,同步语句块

    摘自:http://topmanopensource.iteye.com/blog/1738178 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...

  3. java中的synchronized同步代码块和同步方法的区别

    下面这两段代码有什么区别? //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized ...

  4. 59、synchronized同步代码块

    synchronized同步方法的问题 有些情况下,在方法上面加synchronized同步,会有性能问题.请看下面代码,来计算下两个线程执行的耗时: package com.sutaoyu.Thre ...

  5. 2.2synchronized同步语句块

    使用synchronized虽然能够避免不同步的现象出现,但是也会出现弊端,比如代码执行时间过长,那么其他线程就必须等待该线程执行完毕释放锁之后才能拿到锁. 面对这种问题可以使用同步代码块来解决. 2 ...

  6. 线程同步 synchronized 同步代码块 同步方法 同步锁

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  7. synchronized(){}同步代码块笔记(新手笔记,欢迎纠正)

    /* 内容:同步代码块,目的是解决多线程中的安全问题.什么安全问题呢??就是在执行run方法时,假如线程-0刚刚获得执行权, *还没执行时,就挂那了,这时线程-1获得执行权,并进行执行,就有可能出现负 ...

  8. 线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁

    一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测 ...

  9. synchronized同步代码块锁释放

    今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637  问题线程的内容. &quo ...

随机推荐

  1. 关于pthread_cond_wait使用while循环判断的理解

    在Stevens的<Unix 环境高级编程>中第11章线程关于pthread_cond_wait的介绍中有一个生产者-消费者的例子P311,在进入pthread_cond_wait前使用w ...

  2. Drupal模块的安装方法

    Drupal自身的安装很简单,新建一个数据库,然后根据安装提示一步一步做就OK了. 而Drupal可以通过安装各种模块来提供更多定制功能,这些模块的安装方法基本相同,一般来说,就是以下几步: 1) 从 ...

  3. ssh加密公私钥

    SSH公钥登录原理 在平时工作中我们经常要远程登录服务器,这就要用到SSH协议: $ ssh user@host 主要有两种登录方式:第一种为密码口令登录,第二种为公钥登录 密码口令登录 通过密码进行 ...

  4. WPF教程二:布局之StackPanel面板

    应用程序界面设计中,合理的元素布局至关重要,它可以方便用户使用,并将信息清晰合理地展现给用户.WPF提供了一套功能强大的工具-面板(Panel),来控制用户界面的布局.你可以使用这些面板控件来排布元素 ...

  5. Ubuntu之音效调节

    sudo add-apt-repository ppa:nilarimogard/webupd8 sudo apt-get update sudo apt-get install pulseaudio ...

  6. activiti小结

    前提:业务流程复杂且流程频繁变更的,建议使用工作流:其他情况不建议使用. activiti(v5.14),工作流引擎,基于jbpm.使用建模语言BPMN2.0进行定义. 工作流数据需要写入数据库,ac ...

  7. 标识符的长度应当符合“min-length && max-information”原则

    标识符的长度应当符合“min-length && max-information”原则. 几十年前老 ANSI C 规定名字不准超过 6 个字符,现今的 C++/C 不再有此限制.一 ...

  8. [LeetCode] Subsets II [32]

    题目 Given a collection of integers that might contain duplicates, S, return all possible subsets. Not ...

  9. <iOS>一个开发中值得注意的细节

    UIScrollView有一个属性叫做scrollToTop,是个BOOL值,默认为YES. 它的作用是定义当前的这个UIScrollView的delegate<UIScrollViewDele ...

  10. apache Storm之一-入门学习

    准备工作 这个教程使用storm-starter项目里面的例子.我推荐你们下载这个项目的代码并且跟着教程一起做.先读一下:配置storm开发环境和新建一个strom项目这两篇文章把你的机器设置好. 一 ...