使用java synchronizedd关键字可能会使性能下降100倍是怎么来的

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。
synchronized既可以加在一段代码上,也可以加在方法上。
不要认为给方法或者代码段加上synchronized就万事大吉。
实际上,synchronized(this)以及非static的synchronized方法(至于static synchronized方法请往下看),只能防止多个线程同时执行同一个对象的同步代码段。
synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this。
所以我们在用synchronized关键字的时候,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步。这叫减小锁的粒度,使代码更大程度的并发。原因是基于以上的思想,锁的代码段太长了,别的线程是不是要等很久,等的花儿都谢了。当然这段是题外话,与本文核心思想并无太大关联。
那么,如果真的想锁住这段代码,要怎么做?也就是,如果还是最开始的那段代码,每个线程new一个Sync对象,怎么才能让test方法不会被多线程执行。
解决也很简单,只要锁住同一个对象不就行了。例如,synchronized后的括号中锁同一个固定对象,这样就行了。这样是没问题,但是,比较多的做法是让synchronized锁这个类对应的Class对象。
本文引用:
本文已收录于以下专栏:
相关文章推荐
*synchronize 锁的概念
java的内置锁:
     每个java对象都可以用作一个实现同步的锁,这些锁称为内部锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法...
在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。
Linux老难题解决了!
Linux工程师很多,甚至有很多有多年工作经验,但是对一些关键概念的理解非常模糊,比如不理解CPU、内存资源等的真正分布,具体的工作机制,这使得他们对很多问题的分析都摸不到方向。比如进程的调度延时是多少?linux能否硬实时?多核下多线程如何执行?
方法锁和对象锁说的一个东西,即只有方法锁或对象锁和类锁
对象锁用于对象实例方法,类锁用于类的静态方法或一个类的class对象。类的对象实例可以有很多,不同对象实例的对象锁互不干扰,而每个类只有一个类...
JAVA线程安全关于synchronized关键字的用法,今天才知道原来我一直错了。以为用了synchronized关键字包住了代码就可以线程同步安全了。
测试了下。发现是完全的错了。synchro...
要说明线程同步问题首先要说明Java线程的两个特性,可见性和有序性。多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现。例如,假设在多个线程之间共享了Count类的一个对象,C...
他的最新文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)synchronized关键字详解(转)_C/C++教程_动态网站制作指南
synchronized关键字详解(转)
来源:人气:76
作者:GangWang
出处:/GnagWang/
本文版权归作者和博客园共有,欢迎
中synchronized用法
打个比方:一个object就像一个大房子,大门永远打开。房子里有 很多房间(也就是方法)。
这些房间有上锁的(synchronized方法), 和不上锁之分(普通方法)。房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间。
另外我把所有想调用该对象方法的线程比喻成想进入这房子某个 房间的人。所有的东西就这么多了,下面我们看看这些东西之间如何作用的。
在此我们先来明确一下我们的前提条件。该对象至少有一个synchronized方法,否则这个key还有啥意义。当然也就不会有我们的这个主题了。
一个人想进入某间上了锁的房间,他来到房子门口,看见钥匙在那儿(说明暂时还没有其他人要使用上锁的 房间)。于是他走上去拿到了钥匙
,并且按照自己 的计划使用那些房间。注意一点,他每次使用完一次上锁的房间后会马上把钥匙还回去。即使他要连续使用两间上锁的房间,
中间他也要把钥匙还回去,再取回来。
因此,普通情况下钥匙的使用原则是:“随用随借,用完即还。”
这时其他人可以不受限制的使用那些不上锁的房间,一个人用一间可以,两个人用一间也可以,没限制。但是如果当某个人想要进入上锁的房
间,他就要跑到大门口去看看了。有钥匙当然拿了就走,没有的话,就只能等了。
要是很多人在等这把钥匙,等钥匙还回来以后,谁会优先得到钥匙?Not guaranteed。象前面例子里那个想连续使用两个上锁房间的家伙,他
中间还钥匙的时候如果还有其他人在等钥匙,那么没有任何保证这家伙能再次拿到。 (JAVA规范在很多地方都明确说明不保证,象
Thread.sleep()休息后多久会返回运行,相同优先权的线程那个首先被执行,当要访问对象的锁被 释放后处于等待池的多个线程哪个会优先得
到,等等。我想最终的决定权是在JVM,之所以不保证,就是因为JVM在做出上述决定的时候,绝不是简简单单根据 一个条件来做出判断,而是
根据很多条。而由于判断条件太多,如果说出来可能会影响JAVA的推广,也可能是因为知识产权保护的原因吧。SUN给了个不保证 就混过去了
。无可厚非。但我相信这些不确定,并非完全不确定。因为计算机这东西本身就是按指令运行的。即使看起来很随机的现象,其实都是有规律
可寻。学过 计算机的都知道,计算机里随机数的学名是伪随机数,是人运用一定的方法写出来的,看上去随机罢了。另外,或许是因为要想弄
的确定太费事,也没多大意义,所 以不确定就不确定了吧。)
再来看看同步代码块。和同步方法有小小的不同。
1.从尺寸上讲,同步代码块比同步方法小。你可以把同步代码块看成是没上锁房间里的一块用带锁的屏风隔开的空间。
2.同步代码块还可以人为的指定获得某个其它对象的key。就像是指定用哪一把钥匙才能开这个屏风的锁,你可以用本房的钥匙;你也可以指定
用另一个房子的钥匙才能开,这样的话,你要跑到另一栋房子那儿把那个钥匙拿来,并用那个房子的钥匙来打开这个房子的带锁的屏风。
记住你获得的那另一栋房子的钥匙,并不影响其他人进入那栋房子没有锁的房间。
为什么要使用同步代码块呢?我想应该是这样的:首先对程序来讲同步的部分很影响运行效率,而一个方法通常是先创建一些局部变
量,再对这些变量做一些 操作,如运算,显示等等;而同步所覆盖的代码越多,对效率的影响就越严重。因此我们通常尽量缩小其影响范围。
如何做?同步代码块。我们只把一个方法中该同 步的地方同步,比如运算。
另外,同步代码块可以指定钥匙这一特点有个额外的好处,是可以在一定时期内霸占某个对象的key。还记得前面说过普通情况下钥
匙的使用原则吗。现在不是普通情况了。你所取得的那把钥匙不是永远不还,而是在退出同步代码块时才还。
还用前面那个想连续用两个上锁房间的家伙打比方。怎样才能在用完一间以后,继续使用另一间呢。用同步代码块吧。先创建另外
一个线程,做一个同步代码 块,把那个代码块的锁指向这个房子的钥匙。然后启动那个线程。只要你能在进入那个代码块时抓到这房子的钥匙
,你就可以一直保留到退出那个代码块。也就是说 你甚至可以对本房内所有上锁的房间遍历,甚至再sleep(10*60*1000),而房门口却还有
1000个线程在等这把钥匙呢。很过瘾吧。
在此对sleep()方法和钥匙的关联性讲一下。一个线程在拿到key后,且没有完成同步的内容时,如果被强制sleep()了,那key还一
直在 它那儿。直到它再次运行,做完所有同步内容,才会归还key。记住,那家伙只是干活干累了,去休息一下,他并没干完他要干的事。为
了避免别人进入那个房间 把里面搞的一团糟,即使在睡觉的时候他也要把那唯一的钥匙戴在身上。
最后,也许有人会问,为什么要一把钥匙通开,而不是一个钥匙一个门呢?我想这纯粹是因为复杂性问题。一个钥匙一个门当然更
安全,但是会牵扯好多问题。钥匙 的产生,保管,获得,归还等等。其复杂性有可能随同步方法的增加呈几何级数增加,严重影响效率。这也
算是一个权衡的问题吧。为了增加一点点安全性,导致效 率大大降低,是多么不可取啊。
synchronized的一个简单例子
public class TextThread {
public static void main(String[] args) {
TxtThread tt = new TxtThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
class TxtThread implements Runnable {
int num = 100;
String str = new String();
public void run() {
synchronized (str) {
while (num & 0) {
Thread.sleep(1);
} catch (Exception e) {
e.getMessage();
System.out.intln(Thread.currentThread().getName()
+ "this is " + num--);
上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)
Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如
何?――还得对synchronized关键字的作用进行深入了解才可定论。
总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,
synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
在进一步阐述之前,我们需要明确几点:
A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其
他线程的对象访问。
B.每个对象只有一个锁(lock)与之相关联。
C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
接着来讨论synchronized用到不同地方对代码产生的影响:
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。
1. 把synchronized当作函数修饰符时,示例代码如下:
Public synchronized void methodAAA()
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中
执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了
synchronized关键字的方法。
上边的示例代码等同于如下代码:
public void methodAAA()
synchronized (this)
(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个
拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造
成数据混乱:(
2.同步块,示例代码如下:
public void method3(SomeObject so)
synchronized(so)
这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明
确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:
class Foo implements Runnable
private byte[] lock = new byte[0]; // 特殊的instance变量
Public void methodA()
synchronized(lock) { //… }
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock
= new Object()则需要7行操作码。
3.将synchronized作用于static 函数,示例代码如下:
public synchronized static void methodAAA()
// 同步的static 函数
public void methodBBB()
synchronized(Foo.class)
// class literal(类名称字面常量)
代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这
个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的
目的。P1指的是由Foo类产生的对象。
可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj
在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。
小结如下:
搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。
还有一些技巧可以让我们对共享资源的同步访问更加安全:
1. 定义private 的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以
绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。
2. 如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象
的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并
且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了
优质网站模板1061人阅读
多线程(11)
参考资料:Java 多线程编程核心技术——高洪岩
java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块。
一。synchronized同步方法
①方法内部的变量是线程安全,实类变量非线程安全
package com.
public class HalfSelNum {
private int num = 0 ;
synchronized public void add(String username) {
if(&a&.equals(username)) {
num = 100;
Thread.sleep(100);
System.out.println(&a set over&+num);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
num = 200;
System.out.println(&b set over&+num);
System.out.println(username+& num=&+num);
package com.
public class ThreadA extends Thread{
private HalfSelNum halfSelN
public ThreadA( HalfSelNum halfSelNum) {
// TODO Auto-generated constructor stub
this.halfSelNum = halfSelN
public void run() {
// TODO Auto-generated method stub
//super.run();
halfSelNum.add(&a&);
package com.
public class ThreadB extends Thread{
private HalfSelNum halfSelN
public ThreadB( HalfSelNum halfSelNum) {
// TODO Auto-generated constructor stub
this.halfSelNum = halfSelN
public void run() {
// TODO Auto-generated method stub
//super.run();
halfSelNum.add(&b&);
package com.
public class Run {
public static void main(String[] args) {
HalfSelNum numRef = new HalfSelNum();
HalfSelNum numRef2 = new HalfSelNum();
ThreadA ta = new ThreadA(numRef);
ThreadB tb = new ThreadB(numRef2);
ta.start();
tb.start();
②脏读现象
package com.synch.
public class PublicVar {
public String username = &A&;
public String password = &AA&;
synchronized public void setValue(String username ,String password){
this.username =
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
this.password =
System.out.println(&set method thread name is &+Thread.currentThread().getName()
+&;username:&+username+&;password:&+password);
public void getValue(){
System.out.println(&get method thread name is &+Thread.currentThread().getName()
+&;username:&+username+&;password:&+password);
package com.synch.
public class ThreadA extends Thread{
public PublicVar publicV
public ThreadA(PublicVar publicVar) {
this.publicVar = publicV
public void run() {
// TODO Auto-generated method stub
super.run();
publicVar.setValue(&B&, &BB&);
public static void main(String[] args) {
PublicVar pv = new PublicVar();
ThreadA ta = new ThreadA(pv);
ta.start();
ta.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
pv.getValue();
打印结果:
get methodusername:B;password:AA
& & & &set method thread name is Thread-0;username:B;password:BB
当threadA调用同步方法setValue时,获取了setValue的所在对象的对象锁其它线程必须等threadA执行完后才可以调用setValue,但是可以调用其它非同步方法,
这时只需要在getValue方法上也加上synchronized,这样threadA调用setValue时得到了该方法所在对象的对象锁,其它线程调用getValue同步方法时就无法获取到对象锁只能等threadA释放对象锁。打印结果如下:
set method thread name is Thread-0;username:B;password:BB
& & & &get methodusername:B;password:BB
synchronized有锁重入功能,也就是在使用synchronized时,当一个线程得到一个对象锁后,再次请求该对象锁是可以得到的,线程执行service1时得到了对象锁,而service1内部又调用service2同步方法,这是要再次获取对象锁,是可以得到对象锁的。
package com.synch.
public class Service {
synchronized public void service1() {
System.out.println(&service1............&);
service2();
synchronized public void service2() {
System.out.println(&service2............&);
service3();
synchronized public void service3() {
System.out.println(&service3............&);
package com.synch.
public class MyThread extends Thread{
public void run() {
Service service = new Service();
service.service1();
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
打印结果:
service1............
service2............
& & & service3............
④出现异常会自动释放锁
package com.synch.
import java.util.R
public class Service {
synchronized public void testMethod() {
if(&a&.equals(Thread.currentThread().getName())) {
System.out.println(&threadName:&+Thread.currentThread().getName()+
& run beginTime:&+System.currentTimeMillis());
while(true) {
if((Math.random()+&&).substring(0,8).equals(&0.123456&)) {
System.out.println(&threadName:&+Thread.currentThread().getName()+
& run exception:&+System.currentTimeMillis());
Integer.parseInt(&a&);
System.out.println(&threadName:&+Thread.currentThread().getName()+
& run beginTime:&+System.currentTimeMillis());
package com.synch.
public class Threada extends Thread{
public Threada(Service service) {
// TODO Auto-generated constructor stub
this.service =
public void run() {
// TODO Auto-generated method stub
super.run();
service.testMethod();
package com.synch.
public class Threadb extends Thread{
public Threadb(Service service) {
// TODO Auto-generated constructor stub
this.service =
public void run() {
// TODO Auto-generated method stub
super.run();
service.testMethod();
package com.synch.
public class Run {
public static void main(String[] args) {
Service s = new Service();
Threada ta = new Threada(s);
ta.setName(&a&);
ta.start();
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Threadb tb = new Threadb(s);
tb.setName(&b&);
tb.start();
打印结果:
threadName:a run beginTime:6
threadName:a run exception:9
Exception in thread &a& threadName:b run beginTime:9
java.lang.NumberFormatException: For input string: &a&
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at com.synch.yc.Service.testMethod(Service.java:15)
at com.synch.yc.Threada.run(Threada.java:15)
线程threada出现异常并释放锁,线程theadb执行打印
⑤同步不能继承
package com.synch.
public class Main {
synchronized public void serviceMethod() {
System.out.println(&in main begin threadName:&+Thread.currentThread().getName()+& time:&+System.currentTimeMillis());
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(&in main end threadName:&+Thread.currentThread().getName()+& time:&+System.currentTimeMillis());
package com.synch.
public class Sub extends Main {
public void serviceMethod() {
System.out.println(&in Sub begin threadName:&+Thread.currentThread().getName()+& time:&+System.currentTimeMillis());
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(&in Sub end threadName:&+Thread.currentThread().getName()+& time:&+System.currentTimeMillis());
package com.synch.
public class Threada extends Thread{
public Threada( Sub sub) {
// TODO Auto-generated constructor stub
this.sub =
public void run() {
// TODO Auto-generated method stub
super.run();
sub.serviceMethod();
package com.synch.
public class Threadb extends Thread{
public Threadb( Sub sub) {
// TODO Auto-generated constructor stub
this.sub =
public void run() {
// TODO Auto-generated method stub
super.run();
sub.serviceMethod();
package com.synch.
public class Client {
public static void main(String[] args) {
Sub sub = new Sub();
Threada ta = new Threada(sub);
ta.setName(&a&);
ta.start();
Threadb tb = new Threadb(sub);
tb.setName(&b&);
tb.start();
打印结果:
in Sub begin threadName:a time:3
in Sub begin threadName:b time:4
in Sub end threadName:b time:4
in Sub end threadName:a time:4
可以看出sub的serviceMetod方法是butongbu
二synchronized同步语句块
使用synchronized关键字声明的方法是有弊端的,比如A线程执行的同步方法需要很长时间,那么另外一个线程B想要执行这个方法就需要等待较长的时间,在这个情况下就需要使用synchronized同步语句块。
package com.synch.
public class HalfSelNum {
public void add() {
synchronized (this) {
System.out.println(&threadName:&+Thread.currentThread().getName()+& start:&+System.currentTimeMillis());
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(&threadName:&+Thread.currentThread().getName()+& end:&+System.currentTimeMillis());
package com.synch.
public class ThreadA extends Thread{
private HalfSelNum halfSelN
public ThreadA( HalfSelNum halfSelNum) {
// TODO Auto-generated constructor stub
this.halfSelNum = halfSelN
public void run() {
// TODO Auto-generated method stub
//super.run();
halfSelNum.add();
package com.synch.
public class ThreadB extends Thread{
private HalfSelNum halfSelN
public ThreadB( HalfSelNum halfSelNum) {
// TODO Auto-generated constructor stub
this.halfSelNum = halfSelN
public void run() {
// TODO Auto-generated method stub
//super.run();
halfSelNum.add();
package com.synch.
public class Run {
public static void main(String[] args) {
HalfSelNum numRef = new HalfSelNum();
ThreadA ta = new ThreadA(numRef);
ThreadB tb = new ThreadB(numRef);
ta.start();
tb.start();
打印结果:
threadName:Thread-0 start:0
threadName:Thread-0 end:1
threadName:Thread-1 start:1
threadName:Thread-1 end:1
可以看出和使用synchronized 修饰的方法一样是同步执行的,效率还是没有提高
package com.synch.
public class HalfSelNum {
private String name1 ;
private String name2 ;
public void doTask() {
System.out.println(&begin
Task....................&);
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
String str1= &start run ...........&+Thread.currentThread().getName();
String str2= &start run ...........&+Thread.currentThread().getName();
synchronized (this) {
name1=str1;
name2=str2;
System.out.println(&name1=0&+name1);
System.out.println(&name2=0&+name2);
打印结果:
begin & Task....................
begin & Task....................
name1=0start run ...........Thread-1
name1=0start run ...........Thread-1
name2=0start run ...........Thread-1
name2=0start run ...........Thread-1
当一个线程访问一个对象的同步代码块时,其它线程可以访问该对象的非同步代码块
在使用synchronized(this)时要注意,当一个线程访问synchronized(this)代码块时其它的synchronized(this)代码块将被阻塞。这说明synchronized(this)使用的‘对象监视器’是一个。锁非this对象有一定的优势,若果一个类中有多个synchronized方法,这是使用锁this,会实现同步,但会阻塞,影响效率。如果使用锁非this对象。则synchronized中的程序与同步方法是异步的,不与其他this锁同步方法争抢this锁,则可以大大提高运行效率。
package com.synch.
public class HalfSelNum {
protected String lock = new String();
public void doTask1() {
synchronized (lock) {
System.out.println(& a begin....................&);
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(& a end....................&);
synchronized public void doTask2() {
System.out.println(& b begin....................&);
System.out.println(& b begin....................&);
package com.synch.
public class ThreadA extends Thread{
private HalfSelNum halfSelN
public ThreadA( HalfSelNum halfSelNum) {
// TODO Auto-generated constructor stub
this.halfSelNum = halfSelN
public void run() {
// TODO Auto-generated method stub
//super.run();
halfSelNum.doTask1();
package com.synch.
public class ThreadB extends Thread{
private HalfSelNum halfSelN
public ThreadB( HalfSelNum halfSelNum) {
// TODO Auto-generated constructor stub
this.halfSelNum = halfSelN
public void run() {
// TODO Auto-generated method stub
//super.run();
halfSelNum.doTask2();
package com.synch.
public class Run {
public static void main(String[] args) {
HalfSelNum numRef = new HalfSelNum();
ThreadA ta = new ThreadA(numRef);
ThreadB tb = new ThreadB(numRef);
ta.start();
tb.start();
打印结果:
&a begin....................
&b begin....................
&b begin....................
&a end....................
关键字synchronized还可以对静态方法持锁,如果这样写那是对当前Java文件的Class 类进行持锁。
死锁是程序设计的bug,在程序设计中因避免双方互相持有对方锁,只要互相等待对方锁,就可能出现死锁。
死锁示例:
package com.synch.
public class HalfSelNum extends Thread{
private String locka = new String();
private String lockb = new String();
public String getUsername() {
public void setUsername(String username) {
this.username =
public void run()
if(&a&.equals(username)) {
synchronized (locka) {
System.out.println(&a start time:&+System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
synchronized (lockb) {
System.out.println(&lockb 获取到了&);
synchronized (lockb) {
System.out.println(&b start time:&+System.currentTimeMillis());
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
synchronized (locka) {
System.out.println(&locka 获取到了&);
public static void main(String[] args) {
HalfSelNum a = new HalfSelNum();
a.setUsername(&a&);
Thread ta = new Thread(a);
ta.start();
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
a.setUsername(&b&);
Thread tb = new Thread(a);
tb.start();
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:29564次
积分:1686
积分:1686
排名:千里之外
原创:146篇
(1)(2)(8)(31)(32)(2)(1)(11)(41)(15)(2)(1)(2)(1)

我要回帖

更多关于 synchronized关键字 的文章

 

随机推荐