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. vue 组件 组件2

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>T ...

  2. Python高级特性:Python迭代、生成器、列表生成式

    迭代 给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历称为迭代(Iteration). 在java和C语言中,迭代是通过循环list的下标来完成的,Pyth ...

  3. Java容器深入浅出之Map、HashMap、Hashtable及其它实现类

    在Java中,Set的底层事实上是基于Map实现的,Map内部封装了一个Entry内部接口,由实现类来封装key-value对,当value值均为null时,key的集合就形成了Set.因此,Map集 ...

  4. P4433 [COCI2009-2010#1] ALADIN

    题目描述 给你 n 个盒子,有 q 个操作,操作有两种: 第一种操作输入格式为"1 L R A B",表示将编号为L到R的盒子里的石头数量变为(X−L+1)×A mod B,其中 ...

  5. Hashtable 和 HashMap 以及 ConcurrentHashMap

    备忘: ConcurrentHashMap与Hashtable的区别: Hashtable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能由一个线程对其进行操作:而ConcurrentHash ...

  6. 【刷题】BZOJ 3529 [Sdoi2014]数表

    Description 有一张n×m的数表,其第i行第j列(1<=i<=n,1<=j<=m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. In ...

  7. 洛谷 P4244 [SHOI2008]仙人掌图 II 解题报告

    P4244 [SHOI2008]仙人掌图 II 题目背景 题目这个II是和SHOI2006的仙人掌图区分的,bzoj没有. 但是实际上还是和bzoj1023是一个题目的. 题目描述 如果某个无向连通图 ...

  8. [Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法(转)

    [Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法http://blog.csdn.net/qiujuer/article/details/ ...

  9. 解题:Poetize6 IncDec Sequence

    题面 差分原数列得到差分数组$dif$,这样对于$dif[2]->dif[n]$会多出来两个“空位置”$1$和$n+1$.然后区间加减就变成了使一个位置$+1$,另一个位置$-1$(可以对“空位 ...

  10. jQuery EasyUI 下拉菜单获取日期,最高年份为当前年份,最低年份为当前年份向前推10年

    http://blog.csdn.net/wangjingjing1014/article/details/16885341 <head><meta http-equiv=" ...