synchronized同步方法的问题

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

package com.sutaoyu.Thread;

public class SynchronizedTest02 {
public static long begin1;
public static long end1;
public static long begin2;
public static long end2; public static void main(String[] args) {
final LongTask longTask = new LongTask(); Thread t1 = new Thread() {
public void run() {
begin1 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(true);
end1 = System.currentTimeMillis();
}
}; Thread t2 = new Thread() {
public void run() {
begin2 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(false);
end2 = System.currentTimeMillis();
}
}; t1.start();
t2.start(); //先让主线程睡眠,保证t1和t2线程执行完毕之后再计算时间
try {
Thread.sleep(10000);
}catch(InterruptedException e) {
e.printStackTrace();
} long begin = 0;
long end = 0; //将先执行的线程的时间和最后执行线程的时间获取到
if(begin1 > begin2) {
begin = begin2;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
end = end2;
} System.out.println("两个线程总共耗时:" + (end -begin)/1000 + "秒"); }
}

使用同步代码块完善上面代码

上面代码打印结果是6秒,里面使用Thread.sleep方法来模拟了一个执行耗时较长的代码,假设这段代码并不会涉及到安全问题,所以就没有比较加入同步了。
来使用synchronized代码块来修改下上面的LongTask类。

package com.sutaoyu.Thread;

public class SynchronizedTest02 {
public static long begin1;
public static long end1;
public static long begin2;
public static long end2; public static void main(String[] args) {
final LongTask longTask = new LongTask(); Thread t1 = new Thread() {
public void run() {
begin1 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(true);
end1 = System.currentTimeMillis();
}
}; Thread t2 = new Thread() {
public void run() {
begin2 = System.currentTimeMillis();
//执行耗时较长的任务方法
longTask.changeNum(false);
end2 = System.currentTimeMillis();
}
}; t1.start();
t2.start(); //先让主线程睡眠,保证t1和t2线程执行完毕之后再计算时间
try {
Thread.sleep(10000);
}catch(InterruptedException e) {
e.printStackTrace();
} long begin = 0;
long end = 0; //将先执行的线程的时间和最后执行线程的时间获取到
if(begin1 > begin2) {
begin = begin2;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
begin = begin1;
} if(end1 > end2) {
end = end1;
}else {
end = end2;
} System.out.println("两个线程总共耗时:" + (end -begin)/1000 + "秒"); }
}

修改后将需要同步的代码放到synchronized代码块中,再次运行SynchronizedTest02类,打印结果是3秒,因为那段耗时较长的代码是在异步情况下运行,所以节省了一些时间。

注意:多个线程在执行synchronized同步代码块时,代码块括号里面可以传入任意对象,但一定要保证多个线程访问的是同一个对象。

比如将LongTask中的成员变量Object obj = new Object();移动到changeNum方法中,在t1和t2两个线程中分别调用了changeNum方法,这样会各自创建一个Object对象,仍然会导致线程安全问题发生。

59、synchronized同步代码块的更多相关文章

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

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

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

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

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

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

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

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

  5. synchronized同步代码块锁释放

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

  6. synchronized 同步代码块,售票问题

    package cn.ljs.FristSync; public class SalerDemo extends Thread { static int tickets = 1000; String ...

  7. java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)

    import java.util.concurrent.locks.*; class DuckMsg{ int size;//烤鸭的大小 String id;//烤鸭的厂家和标号 DuckMsg(){ ...

  8. Java:多线程,线程同步,synchronized关键字的用法(同步代码块、非静态同步方法、静态同步方法)

    关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨synchronized关键字. sy ...

  9. 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法

    主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...

随机推荐

  1. ANR基础

    转自:http://blog.sina.com.cn/s/blog_c0de2be70102wd1k.html 1.ANR basic knowledge ANR分类: Key Dispatch Ti ...

  2. QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)

    前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...

  3. Codeforces 449B_Jzzhu and Cities

    给一个无向图,外加一些特殊的连接原点的无向边.在不改变原点与所有点的最短路的情况下,最多可以删除多少条特殊边? 首先我们把所有的边夹杂在一起.spfa跑出与所有点的最短路. 接下来我们通过一次bfs来 ...

  4. POJ1637_Sightseeing tour

    给一个联通图,有的是单向边,有的是双向边,问是否存在欧拉回路. 乍一看毫无思路,可以这样来搞,对于每条无向边,我们随便指定一个方向,看看是否能够做到所有点的度数之和为偶数. 接下来,对于我们指定的边, ...

  5. spring1 注册value与ref的区别

  6. java 创建过程

  7. Day24-图片验证码----待续

    一,上课所讲---------没听懂!!! 1,首先,图片验证码不能放到客户浏览器的cookie上,否则,客户可以直接从它的浏览器上拿到,然后自动提交,这样的话,验证码就没有任何用处了.所以图片验证码 ...

  8. Linux服务器中安装python包管理工具pip

    pip是python的包管理工具,python的强大之处除了在于语法的简练,还有就是对众多的库支持了. 1.下载pip包管理工具 链接地址:https://pypi.python.org/pypi/p ...

  9. 【刷题】LOJ 6000 「网络流 24 题」搭配飞行员

    题目描述 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭 ...

  10. Unity使用C#实现简单Scoket连接及服务端与客户端通讯

    简介: 网络编程是个很有意思的事情,偶然翻出来很久之前刚开始看Socket的时候写的一个实例,贴出来吧 Unity中实现简单的Socket连接,c#中提供了丰富的API,直接上代码. 服务端代码: [ ...