synchronized同步语句块

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

synchronized方法的弊端

package Second;

public class Task {

    private String getData1;
private String getData2; public synchronized void doLongTimeTask() {
try {
System.out.println("begin task");
Thread.sleep(3000);
getData1 = "长时间处理任务后从远程返回的值1threadName="
+ Thread.currentThread().getName();
getData2 = "长时间处理任务后从远程返回的值2threadName="
+ 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 Second;

public class CommonUtils {

    public static long beginTime1;
public static long endTime1; public static long beginTime2;
public static long endTime2;
}
package Second;

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 Second;

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 Second;

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));
}
}

synchronized同步代码块的使用

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

package Second;

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 Second;

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 Second;

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 Second;

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();
} }

虽然使用了同步代码块,但执行的效率还是没有提高

用同步代码块解决同步方法的弊端

package Second;

public class CommonUtils {

    public static long beginTime1;
public static long endTime1; public static long beginTime2;
public static long endTime2;
}
package Second;

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 Second;

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 Second;

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();
}
}
}
package Second;

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 Second;

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 Second;

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 Second;

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 Second;

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代码块间的同步性

当一个线程访问object的一个同步代码块时,其他线程对同一个object中所有其他的同步代码块的访问将被阻塞。这说明synchronized使用的时一个“对象监视器”

package Second;

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 end=" + 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 end=" + System.currentTimeMillis());
}
}
}
package Second;

public class ThreadA extends Thread {

    private ObjectService service;

    public ThreadA(ObjectService service) {
super();
this.service = service;
} @Override
public void run() {
super.run();
service.serviceMethodA();
} }
package Second;

public class ThreadB extends Thread {
private ObjectService service; public ThreadB(ObjectService service) {
super();
this.service = service;
} @Override
public void run() {
super.run();
service.serviceMethodB();
}
}
package Second;

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();
} }

两个代码块按顺序执行

验证同步代码块是锁定当前对象的

package Second;

public class Task {

    public void otherMethod() {
System.out.println("------------------------run--otherMethod");
} public void doLongTimeTask() {
synchronized (this) {
for (int i = 0; i < 10000; i++) {
System.out.println("synchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
} }
}
package Second;

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 Second;

public class MyThread2 extends Thread {

    private Task task;

    public MyThread2(Task task) {
super();
this.task = task;
} @Override
public void run() {
super.run();
task.otherMethod();
} }
package Second;

public class Run {

    public static void main(String[] args) throws InterruptedException {
Task task = new Task(); MyThread1 thread1 = new MyThread1(task);
thread1.start(); Thread.sleep(100); MyThread2 thread2 = new MyThread2(task);
thread2.start();
}
}

package Second;

public class Task {

    synchronized public void otherMethod() {
System.out.println("------------------------run--otherMethod");
} public void doLongTimeTask() {
synchronized (this) {
for (int i = 0; i < 10000; i++) {
System.out.println("synchronized threadName="
+ Thread.currentThread().getName() + " i=" + (i + 1));
}
} }
}

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

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

参考:https://www.cnblogs.com/QQParadise/articles/5059824.html

《Java多线程编程核心技术》读后感(三)的更多相关文章

  1. java多线程编程核心技术——第三章

    第一节等待/通知机制 1.1不使用等待/通知机制实现线程间的通讯 1.2什么是等待/通知机制 1.3等待/通知机制的实现 1.4方法wait()锁释放与notify()锁不释放 1.5当interru ...

  2. java多线程编程核心技术——第三章总结

    第一节等待/通知机制 1.1不使用等待/通知机制实现线程间的通讯 1.2什么是等待/通知机制 1.3等待/通知机制的实现 1.4方法wait()锁释放与notify()锁不释放 1.5当interru ...

  3. java多线程编程核心技术(三)--线程间通信

    1.等待/通知机制 1.wait()方法:使当前执行代码的线程进行等待.wait()方法是Object类的方法,该方法将当前线程放入“预执行队列”中,并在wait()所处的代码行处停止执行.只到被唤起 ...

  4. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  5. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

  6. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  7. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  8. Java多线程编程核心技术(二)对象及变量的并发访问

    本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...

  9. Java多线程编程核心技术(一)Java多线程技能

    1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...

  10. 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析

    不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08       ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...

随机推荐

  1. iOS_39_触摸解锁

    终于效果图: 控制器: // // BeyondViewController.m // 39_触摸解锁 // // Created by beyond on 14-9-17. // Copyright ...

  2. python 基础 1.6 python 帮助信息及数据类型间相互转换

      一. 帮助信息   # dir() 方法  查看函数的方法   # help()   # type() 查看类型   name = raw_input('please input you name ...

  3. SASL mechanism

    <property> <name>hive.spark.client.rpc.sasl.mechanisms</name> <value>DIGEST- ...

  4. synchronized同步关键字

    参考:http://blog.csdn.net/luoweifu/article/details/46613015 synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: ...

  5. 谷歌postman插件的安装与使用

    下载地址:http://pan.baidu.com/s/1kTh1g4B 安装方法: 1.下载并解压 2.解压后.打开谷歌浏览器.选择很多其它工具→扩展程序,如图 3.勾选开发人员模式 4.选择载入正 ...

  6. ZookeeperclientAPI之创建会话(六)

    Zookeeper对外提供了一套Java的clientAPI. 本篇博客主要讲一下创建会话. 创建项目 首选,创建一个基于maven管理的简单javaproject.在pom文件里引入zookeepe ...

  7. iOS SDK:iOS调试技巧

    感谢原创 在程序中,无论是你想弄清楚为什么数组中有3个对象而不是5个,或者为什么一个新的玩家开始之后,游戏在倒退——调试在这些处理过程中是比较重要的一部分.通过本文的学习,我们将知道在程序中,可以使用 ...

  8. css的核心

    css核心内容--流 流:在现实生活中就是流水,在网页设计中就是元素的排列方式. 标准流:元素在网页中就像流水,排在前面的元素内容前面出现,排在后面的元素内容后面显示. 这种布局方式就称为标准流的布局 ...

  9. 第十五章-Web开发

    随着web的发展, 最开始使用的CS架构已经不适合web了, 现在web使用的架构是BS架构 如今大部分重量级的软件都以web形式提供了 web开发的四个阶段 1) 静态web页面 2) CGI: 静 ...

  10. FileHeader 详解文件头部注释-sublimeText

    FileHeader 前言: 直奔主题吧,sublimeText 的大部分插件都是非常好用,易用的,而且很容易找到资料.这次用 FileHeader 发现网上的资料很少,而且大部分说得都很模糊,或者直 ...