学习整理——Java同步synchronized关键字

本文总结自:Java线程同步:synchronized锁住的是代码还是对象


结论:

1.synchronized修饰的非static方法其实是在执行方法前,先获取this对象的锁,如果对象锁被其他线程获取了,则进入阻塞状态;

2.synchronized(mutex)修饰的代码段是先获取mutex对象的锁,然后再进入代码段,否则进入阻塞;

3.对于synchronized修饰static方法,如1.差不多,只不过现在是获取该类的class对象,由于一个类只有一个class对象,这时可以真正做到只有一个线程能够执行该代码段;

4.设计同步时,尽量避免直接使用synchronized修饰的非static方法,尽量缩小核心的同步代码段,最大化利用CPU;

5.实例化多个含有synchronized代码段的对象时,可能由于设置的对象锁是非全局的,依然可以有多个线程同时执行同一个代码段。


代码

实例化多个对象,在多个线程里执行synchronized修饰的非static方法。

package cc.appweb.www;

public class SynchTest {
	
	public static void main(String[] args){
		Sy[] sys = new Sy[5];
		WorkThread[] workThread = new WorkThread[5];
		for(int i = 0 ; i < 5 ; i++){
			sys[i] = new Sy();
			workThread[i] = new WorkThread();
			workThread[i].setPara(sys[i], i);
			workThread[i].start();
		}
		try{
			Thread.sleep(2000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Main Thread end!");
	}
}

class Sy{
	public synchronized void run(int flag){
		System.out.println("Instance "+flag + " run!" );
		try{
			Thread.sleep(1000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Instance " + flag + " end!" );
	}
}

class WorkThread extends Thread{
	private Sy worker;
	private int flag;
	
	public void setPara(Sy sy, int flag){
		worker = sy;
		this.flag = flag;
	}
	
	@Override
	public void run(){
		worker.run(flag);
	}
}

输出

Instance 0 run!
Instance 1 run!
Instance 3 run!
Instance 4 run!
Instance 2 run!
Instance 0 end!
Instance 1 end!
Instance 2 end!
Instance 4 end!
Instance 3 end!
Main Thread end!
这时多个线程可以同时执行同一个代码段,因为获取的对象锁都不同


将多个Sy实例修改为一个Sy实例

package cc.appweb.www;

public class SynchTest {
	
	public static void main(String[] args){
		//Sy[] sys = new Sy[5];
		Sy sy = new Sy();
		WorkThread[] workThread = new WorkThread[5];
		for(int i = 0 ; i < 5 ; i++){
			//sys[i] = new Sy();
			workThread[i] = new WorkThread();
			workThread[i].setPara(sy, 1);
			workThread[i].start();
		}
		try{
			//Thread.sleep(2000);
			Thread.sleep(20000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Main Thread end!");
	}
}

class Sy{
	public synchronized void run(int flag){
		System.out.println("Instance "+flag + " run!" );
		try{
			Thread.sleep(1000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Instance " + flag + " end!" );
	}
}

class WorkThread extends Thread{
	private Sy worker;
	private int flag;
	
	public void setPara(Sy sy, int flag){
		worker = sy;
		this.flag = flag;
	}
	
	@Override
	public void run(){
		worker.run(flag);
	}
}
输出

Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Instance 1 run!
Instance 1 end!
Main Thread end!
可见run 和 end变成了成对出现,也就是说其他线程执行run方法时被阻塞了。


生成多个实例,在方法里获取本身对象

package cc.appweb.www;

public class SynchTest {
	
	public static void main(String[] args){
		Sy[] sys = new Sy[5];
		//Sy sy = new Sy();
		WorkThread[] workThread = new WorkThread[5];
		for(int i = 0 ; i < 5 ; i++){
			sys[i] = new Sy();
			workThread[i] = new WorkThread();
			workThread[i].setPara(sys[i], i);
			workThread[i].start();
		}
		try{
			Thread.sleep(2000);
			//Thread.sleep(20000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Main Thread end!");
	}
}

class Sy{
	public void run(int flag){
		synchronized (this) {
			System.out.println("Instance "+flag + " run!" );
 			try{
                                               Thread.sleep(1000);
                                    }catch (Exception e) {
                                               e.printStackTrace();
                                    }
                                    System.out.println("Instance " + flag + " end!" );
                         }
            }
}

class WorkThread extends Thread{
            private Sy worker;
            private int flag;
            public void setPara(Sy sy, int flag){
                         worker = sy;
                         this.flag = flag;
            }

            @Override
            public void run(){
                         worker.run(flag);
            }
}


</pre><p></p><pre>
输出

Instance 0 run!
Instance 2 run!
Instance 1 run!
Instance 3 run!
Instance 4 run!
Instance 1 end!
Instance 0 end!
Instance 4 end!
Instance 3 end!
Instance 2 end!
Main Thread end!
依然会同时执行该代码段


生成多个实例,在方法里获取该类的class对象

class Sy{
	public void run(int flag){
		synchronized (Sy.class) {
			System.out.println("Instance "+flag + " run!" );
			try{
				Thread.sleep(1000);
			}catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("Instance " + flag + " end!" );
		}
	}
}
输出

Instance 0 run!
Instance 0 end!
Instance 4 run!
Instance 4 end!
Instance 3 run!
Instance 3 end!
Instance 2 run!
Instance 2 end!
Instance 1 run!
Instance 1 end!
Main Thread end!
这时run和end也成对出现了。


测试synchronized static方法

package cc.appweb.www;

public class SynchTest {
	
	public static void main(String[] args){
		WorkThread[] workThreads = new WorkThread[5];
		for(int i = 0; i < 5 ; i++){
			workThreads[i] = new WorkThread(i);
			workThreads[i].start();
		}
		
		try{
			Thread.sleep(10000);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class Sy{
	
	public synchronized static void staticRun(int flag){
		System.out.println("Instance " + flag + " run!");
		try{
			Thread.sleep(1000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Instance " + flag + " end!" );
	} 
}

class WorkThread extends Thread{
	
	private int flag;
	public WorkThread(int flag){
		this.flag = flag;
	}
	
	@Override
	public void run(){
		Sy.staticRun(flag);
	}
}
输出

Instance 0 run!
Instance 0 end!
Instance 3 run!
Instance 3 end!
Instance 4 run!
Instance 4 end!
Instance 2 run!
Instance 2 end!
Instance 1 run!
Instance 1 end!


为了说明synchronized static 方法获取的是类的class对象,可以在方法内添加wait,notify的调用。

package cc.appweb.www;

public class SynchTest {
	
	public static void main(String[] args){
		WorkThread[] workThreads = new WorkThread[5];
		for(int i = 0; i < 5 ; i++){
			workThreads[i] = new WorkThread(i);
			workThreads[i].start();
		}
		
		try{
			Thread.sleep(10000);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class Sy{
	
	private static int count=0;
	public synchronized static void staticRun(int flag){
		count ++;
		System.out.println("Instance " + flag + " run!");
		try{
			if(count != 5 )  // 控制线程的等待
				Sy.class.wait();
			Thread.sleep(1000);
		}catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Instance " + flag + " end!" );

		Sy.class.notify();
	} 
}

class WorkThread extends Thread{
	
	private int flag;
	public WorkThread(int flag){
		this.flag = flag;
	}
	
	@Override
	public void run(){
		Sy.staticRun(flag);
	}
}
输出

Instance 0 run!
Instance 3 run!
Instance 2 run!
Instance 1 run!
Instance 4 run!
Instance 4 end!
Instance 0 end!
Instance 3 end!
Instance 2 end!
Instance 1 end!
run和end已经不成对出现,说明获取的就是class对象。


















生成多个实例,在方法里获取本身对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值