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. mysql EXPLAIN 参数表

    测试样式: 参数详情:

  2. 安装iproute2

    yum install -y gcc bison flex #tar -xzf  iproute2-3.17.0.tar.gz #cd iproute2-3.17.0#sed -i '/^TARGET ...

  3. log4j2分析总结(一)

    现在公司用log4j2 进行日志记录,我也看了相关的资料,现在进行记录学习总结下 整体结构 Appenders里设置日志的输出方式.级别和格式 Loggers里设置全局的级别和绑定appenders里 ...

  4. SPOJ_SUBLEX

    经典题目:给一个字符串,求字典序第k小的子串是什么. 涉及子串问题,上自动机. 首先我们可以用记忆化搜索的方法,求出到达某一个状态后,能产生多少个新状态. 首先,到达这个状态就不走了,这肯定是一种状态 ...

  5. 【uoj#213】[UNR #1]争夺圣杯 单调栈+差分

    题目描述 给出一个长度为 $n$ 的序列,对于 $1\sim n$ 的每一个数 $i$ ,求这个序列所有长度为 $i$ 的子区间的最大值之和,输出每一个 $i$ 的答案模 $998244353$ 后异 ...

  6. 对\${ctx}的一点理解

    一.\${ctx}与${pageContext.request.contextPath}的区别 相同点: \${ctx}和\${pageContext.request.contextPath}都是获取 ...

  7. 模板:插头dp

    前言: 严格来讲有关dp的都不应该叫做模板,因为dp太活了,但是一是为了整理插头dp的知识,二是插头dp有良好的套路性,所以姑且还叫做模板吧. 这里先推荐一波CDQ的论文和这篇博客http://www ...

  8. CF1009F Dominant Indices 解题报告

    CF1009F Dominant Indices 题意简述 给出一颗以\(1\)为跟的有根树,定义\(d_{i,j}\)为以\(i\)为根节点的子树中到\(i\)的距离恰好为\(j\)的点的个数,对每 ...

  9. 为什么redis支持lua脚本功能

    看看大家怎么说! 参考: (1)描述界面:WOW和剑网三的界面都是用LUA写的: (2)沟通引擎:游戏图形引擎提供了一些接口库,可以在LUA中调用: (3)服务器端:有些游戏,例如剑网三,在服务器端也 ...

  10. React事件传递参数

    <button onClick={(ev) => {this.handleClick(ev,arg1,arg2,...)}} 用箭头函数,注意第一个参数一定要是事件参数.