多线程--synchronized同步方法

Posted z-xiaoyao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程--synchronized同步方法相关的知识,希望对你有一定的参考价值。

1、方法中的变量不存在非线程安全问题


HasSelfPrivateNum	publicclassHasSelfPrivateNum
	publicvoidaddI(Stringusername)
	try
	intnum=0;
	if(username.equals("a"))
	num=100;
	System.out.println("asetover");
	Thread.sleep(2000);
	else
	num=200;
	System.out.println("bsetover");
	
	System.out.println(username+"num="+num);
	
	catch(InterruptedExceptione)
	e.printStackTrace();
	
	
	
ThreadA	publicclassThreadAextendsThread
	
	privateHasSelfPrivateNumnumRef;
	publicThreadA(HasSelfPrivateNumnumRef)
	super();
	this.numRef=numRef;
	
	@Override
	publicvoidrun()
	super.run();
	numRef.addI("a");
	
	
ThreadB	publicclassThreadBextendsThread
	
	privateHasSelfPrivateNumnumRef;
	publicThreadB(HasSelfPrivateNumnumRef)
	super();
	this.numRef=numRef;
	
	@Override
	publicvoidrun()
	super.run();
	numRef.addI("b");
	
	
Run	publicclassRun
	publicstaticvoidmain(String[]args)
	HasSelfPrivateNumnumRef=newHasSelfPrivateNum();
	ThreadAathread=newThreadA(numRef);
	athread.start();
	ThreadBbthread=newThreadB(numRef);
	bthread.start();
	
	


2、多个线程访问对象变量,出现非线程安全问题

改动

private intnum=0放在类中,而不是方法中

结果

值被覆盖(出现线程安全问题)

解决

addI方法上加synchronized


3、创建多个对象会产生多个锁

改动

run类中创建多个HasSelfPrivateNum实例对象即可


4、A线程先持有object对象的Lock锁,B线程可以以异步的方式调用object对象中的非synchronized类型的方法

      A线程先持有object对象的Lock锁,B线程如果在这时调用object对象中的synchronized类型的方法则需要等待,也就是同步

MyObject	publicclassMyObject
	synchronizedpublicvoidmethodA()
	try
	System.out.println("beginmethodAthreadName="+Thread.currentThread().getName());
	Thread.sleep(5000);
	System.out.println("endendTime="+System.currentTimeMillis());
	catch(InterruptedExceptione)
	e.printStackTrace();
	
	
	
	synchronizedpublicvoidmethodB()
	try
	System.out.println("beginmethodBthreadName="+Thread.currentThread().getName()+"begintime="+System.currentTimeMillis());
	Thread.sleep(5000);
	System.out.println("end");
	catch(InterruptedExceptione)
	e.printStackTrace();
	
	
	
ThreadA	publicclassThreadAextendsThread
	
	privateMyObjectobject;
	publicThreadA(MyObjectobject)
	super();
	this.object=object;
	
	@Override
	publicvoidrun()
	super.run();
	object.methodA();
	
	
ThreadB	publicclassThreadBextendsThread
	
	privateMyObjectobject;
	publicThreadB(MyObjectobject)
	super();
	this.object=object;
	
	@Override
	publicvoidrun()
	super.run();
	object.methodB();
	
	
Run	publicclassRun
	publicstaticvoidmain(String[]args)
	MyObjectobject=newMyObject();
	ThreadAa=newThreadA(object);
	a.setName("A");
	ThreadBb=newThreadB(object);
	b.setName("B");
	a.start();
	b.start();
	
	


5、脏读

A线程调用anyObject对象加入synchronized关键字的X方法时,其他线程必须等A线程执行完毕才可以调用X方法,但B线程可以随意调用其他非synchronized同步方法

A线程调用anyObject对象加入synchronized关键字的X方法时,B线程如果调用synchronized关键字的非X方法时,必须等A线程将X方法执行完才可以调用


6、synchronized锁重入

一个synchronized方法的内部调用本类的其他synchronized方法时,是可以得到锁的

 当存在父子类继承关系时,子类完全可以通过“可重入锁”调用父类的同步方法


7、  a线程出现异常并释放锁,b线程进入方法正常打印,也就是说出现异常的锁被自动释放了

Service	publicclassService
	synchronizedpublicvoidtestMethod()
	if(Thread.currentThread().getName().equals("a"))
	System.out.println("ThreadName="+Thread.currentThread().getName()+"runbeginTime="+System.currentTimeMillis());
	inti=1;
	while(i==1)
	if((""+Math.random()).substring(0,8).equals("0.123456"))
	System.out.println("ThreadName="+Thread.currentThread().getName()+"runexceptionTime="+System.currentTimeMillis());
	Integer.parseInt("a");
	
	
	else
	System.out.println("ThreadBrunTime="+System.currentTimeMillis());
	
	
	
ThreadA	publicclassThreadAextendsThread
	
	privateServiceservice;
	publicThreadA(Serviceservice)
	super();
	this.service=service;
	
	@Override
	publicvoidrun()
	service.testMethod();
	
	
ThreadB	publicclassThreadBextendsThread
	
	privateServiceservice;
	publicThreadB(Serviceservice)
	super();
	this.service=service;
	
	@Override
	publicvoidrun()
	service.testMethod();
	
	
Run	publicclassRun
	publicstaticvoidmain(String[]args)
	try
	Serviceservice=newService();
	ThreadAa=newThreadA(service);
	a.setName("a");
	a.start();
	Thread.sleep(500);
	ThreadBb=newThreadB(service);
	b.setName("b");
	b.start();
	catch(InterruptedExceptione)
	e.printStackTrace();
	
	
	


8、同步不能继承,父类的方法中有synchronized关键字,运行子类的方法时,必须在子类的方法中添加synchronized关键字,才可以实现同步运行


以上是关于多线程--synchronized同步方法的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程-synchronized(非this对象)

Synchronized关键字与多线程

多线程-6

java 多线程系列基础篇之 synchronized关键字

java多线程核心技术——synchronized同步方法与synchronized同步快

Java多线程同步方法