synchronized:同步锁

synchronized

synchronized关键字:同步, 反义词 asynchronized 异步
同步资源,同步锁

  • 此关键字可以修饰在方法上
    比如:
    public synchronized void method(){
    //代码块
    }
    当线程1调用method方法时,就会给method方法添加一个锁
    如果方法不执行完毕,其他线程就不会执行此代方法,线程排队等待

  • 此关键字修饰在对象上
    比如:
    synchronized(某个对象){
    //同步代码块
    }
    当线程1执行同步代码块时,就会给同步代码块添加一个锁
    如果代码块不执行完毕,其他线程就不会执行此代码块,线程排队等待

  • 此关键字修饰在类上
    比如 :
    synchronized (类名.class){
    //同步代码块

    }
    当线程1执行同步代码块时,就会给类添加一个锁
    如果代码块不执行完毕,其他线程就不会执行此代码块,线程排队等待

    下面来具体介绍

synchronized同步方法测试

案例一

synchronized作用在同一个实例对象(test)上,
两个线程,一个线程调用synchronized修饰的方法,另一个调用普通的方法

public class SynchronizedTest1 {
   public synchronized void methodA(){
   	try{
   		for(int i=0;i<5;i++){
   			System.out.println("methodA="+i);
   			Thread.sleep(1000);
   		}			
   	}catch (Exception e){
   		e.printStackTrace();
   	}
   }
   public void methodB(){
   	try{
   		for(int i=0;i<5;i++){
   			System.out.println("methodB="+i);
   			Thread.sleep(1000);
   		}
   		
   	}catch (Exception e){
   		e.printStackTrace();
   	}
   }
   public static void main(String[] args) {
   	SynchronizedTest1 test =new SynchronizedTest1();
   	
   	Thread t1 =new Thread(new Runnable(){

   		@Override
   		public void run() {
   			test.methodA();
   			
   		}
   		
   	});
   	t1.start();
   	Thread t2 =new Thread(new Runnable(){

   		@Override
   		public void run() {
   			test.methodB();
   			
   		}
   		
   	});
   	t2.start();
   }

}
/*-  运行结果:
   methodA=0
   methodB=0
   methodA=1
   methodB=1
   methodA=2
   methodB=2
   methodB=3
   methodA=3
   methodA=4
   methodB=4
   */

我们可以看出,结果是A,B是在并行运行,synchronized关键字这里没有体现出来

案例二

1.作用在同一个实例对象test1上,synchronized同步方法测试

2.用不同实例对象(test1和test2)调用不同方法

public class SynchronizedTest1_1 {
	public synchronized void methodA(){
		try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public synchronized void methodB(){
		try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		SynchronizedTest1_1 test1 =new SynchronizedTest1_1();
		//SynchronizedTest1_1 test2 =new SynchronizedTest1_1();
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				//test2.methodB();
			}
			
		});
		t2.start();
	}

}
/*1.实验结果
methodA=0
methodA=1
methodA=2
methodA=3
methodA=4
methodB=0
methodB=1
methodB=2
methodB=3
methodB=4
*/2.

从实验结果,我们可以看出,两个不同的线程,用同一个对象调用不同的方法,并且两个方法都被synchronized修饰,所以这是给同一个对象加锁.是用同一个对象test1分别调用methodA和methodB,此时给methodA给test1加锁,当线程t2,去调用methodB时,要等待test1从methodA中(解锁)释放,此时是串行,
如果是两个对象调用不同的方法就是并行了.,两个对象互不干扰

案例三

作用在同一个实例对象test1上,

public class SynchronizedTest1_2 {
	public synchronized void methodA(){
		try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public synchronized void methodB(){
		try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		SynchronizedTest1_2 test1 =new SynchronizedTest1_2();
		//SynchronizedTest1_2 test2 =new SynchronizedTest1_2();
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				//test2.methodA();
			}
			
		});
		t2.start();
	}

}
/*实验结果
methodA=0
methodA=1
methodA=2
methodA=3
methodA=4
methodA=0
methodA=1
methodA=2
methodA=3
methodA=4
*/

从实验结果我们看出,两个线程,但是是同一个对象(test1),调用同一个方法,结果是串行运行,也就是说需要等着test1从上一个线程中释放,下一个才可以使用,但如果是两个不同的对象,就是并行运行,所以这里synchronized锁的是对象(test1).

synchronized同步代码块测试

案例四

作用在同一个实例对象上,
两个线程,一个线程调用synchronized代码块
另一个线程可以调用非synchronized修饰的代码块,

public class SynchronizedTest2 {
	
	public  void methodA(){//方法可以异步运行,进来以后内容同步了
		//同步代码块  this本类对象
		synchronized (this){
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
			}catch (Exception e){
			e.printStackTrace();
			}
		}
		
	}
	public void methodB(){
		
		try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		SynchronizedTest2 test1 =new SynchronizedTest2();
		
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				
			}
			
		});
		t2.start();
	}

}
/*实验结果
methodA=0
methodB=0
methodB=1
methodA=1
methodB=2
methodA=2
methodA=3
methodB=3
methodB=4
methodA=4
*/

从实验结果可以看出,两个互不干扰,并行运行

案例五

作用在同一个实例对象上, synchronized同步代码块测试
两个线程,一个对象调用,两个synchronized修饰的代码块

public class SynchronizedTest2_1 {
	//同步代码块
	public  void methodA(){
		synchronized(this){
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
			}catch (Exception e){
			e.printStackTrace();
			}
		}
			
		}
		
	
   //给代码块加同步
	public void methodB(){
		synchronized (this){
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		   }catch (Exception e){
			e.printStackTrace();
		   }
		}
		
	}
	public static void main(String[] args) {
		SynchronizedTest2_1 test1 =new SynchronizedTest2_1();
		//SynchronizedTest2_1 test2 =new SynchronizedTest2_1();
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				//test2.methodB();
			}
			
		});
		t2.start();
	}

}
/*实验结果
methodA=0
methodA=1
methodA=2
methodA=3
methodA=4
methodB=0
methodB=1
methodB=2
methodB=3
methodB=4
*/

方法并没有被上锁,但内容代码被上锁了,从实验结果可以看出,当线程1执行,test1调用A时被锁住,当A执行完,释放资源之后,test1才可以被线程2使用调用B,所以此时线程1,2是串行的,
但如果是两个不同的对象调用不同的方法时,就是并行的了

synchronized同步代码块测试和同步方法测试

案例六

作用在作用在同一个实例对象上
1,synchronized和synchronized(this)

public class SynchronizedTest3 {
	//给方法加锁
	public synchronized void methodA(){
		
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
			}catch (Exception e){
			e.printStackTrace();
			}
		
	}
	//给代码块加锁
	public void methodB(){
		synchronized (this) {
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
		}
		
	}
	public static void main(String[] args) {
		SynchronizedTest3 test1 =new SynchronizedTest3();
		
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				
			}
			
		});
		t2.start();
	}

}
/*实验结果
methodA=0
methodA=1
methodA=2
methodA=3
methodA=4
methodB=0
methodB=1
methodB=2
methodB=3
methodB=4
*/

从实验结果可以看出,synchronized和synchronized(this)二者没有区别,都是作用在this对象上,给this对象加锁,所以会同步,串行运行

案例六

作用在同一个实例对象上, synchronized同步代码块测试和同步方法测试

public class SynchronizedTest3_1 {
	//给方法加锁
	public synchronized void methodA(){
		
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
			}catch (Exception e){
			e.printStackTrace();
			}
		
	}
	//给代码块加锁
	public void methodB(){
		synchronized (this) {
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
		}
		
	}
	public void methodC(){
		//可以是new任何对象
		Object obj = new Object();
		synchronized (obj) {
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodC="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
		}
		
	}
	
	public static void main(String[] args) {
		SynchronizedTest3_1 test1 =new SynchronizedTest3_1();
		
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				
			}
			
		});
		t2.start();
		
		Thread t3 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodC();
				
			}
			
		});
		t3.start();
	}

}
/*实验结果
methodC=1
methodA=2
methodC=2
methodA=3
methodC=3
methodA=4
methodC=4
methodB=0
methodB=1
methodB=2
methodB=3
methodB=4
*/

从实验结果得出synchronized和synchronized(this) 都是作用在this对象上,给this对象加锁而synchronized(obj) 这个是作用在obj对象上,给obj对象添加锁,
所以A和B是串行的,此时C与(A和B)是并行

案例七

作用在同一个实例对象上, synchronized同步代码块测试和同步方法测试

public class SynchronizedTest3_2 {
	private Object obj =new Object();

		//给方法加锁
		public synchronized void methodA(){
			
				try{
				for(int i=0;i<5;i++){
					System.out.println("methodA="+i);
					Thread.sleep(1000);
				}
				
				}catch (Exception e){
				e.printStackTrace();
				}
			
		}
		//给代码块加锁
		public void methodB(){
			synchronized (obj) {
				try{
				for(int i=0;i<5;i++){
					System.out.println("methodB="+i);
					Thread.sleep(1000);
				}
				
			}catch (Exception e){
				e.printStackTrace();
			}
			}
			
		}
	public void methodC(){
		//new任何对象
		
		synchronized (obj){
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodC="+i);
				Thread.sleep(1000);
			}
			
		    }catch (Exception e){
			    e.printStackTrace();
		    }
		  }
		
	}
	public static void main(String[] args) {
		SynchronizedTest3_2 test1 =new SynchronizedTest3_2();
		
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				
			}
			
		});
		t2.start();
		Thread t3 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodC();
				
			}
			
		});
		t3.start();
	}

}

/*实验结果
methodA=0
methodB=0
methodA=1
methodB=1
methodA=2
methodB=2
methodB=3
methodA=3
methodA=4
methodB=4
methodC=0
methodC=1
methodC=2
methodC=3
methodC=4
*/

从实验结果可以看出synchronized修饰的A方法针对的是this对象,而B和C中的synchronized(obj)代码块修饰的是obj对象,所以,methodB和methodC是串行,锁上在obj上,methodA跟(B和C)是并行的

作用在同一个类上,一个类上只有一把锁

案例八

synchronized类锁
static synchronized 和 synchronized(类名.class)

public class SynchronizedTest4 {
	//static的修饰的方法属于类
	public synchronized static  void methodA(){//加静态就锁在类上了
		//同步代码块
		
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
			}catch (Exception e){
			e.printStackTrace();
			}
		
	}
	public void methodB(){
		synchronized (SynchronizedTest4.class){//修饰在类上了
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
		}
		
	}
	public static void main(String[] args) {
		SynchronizedTest4 test1 =new SynchronizedTest4();
		
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				
			}
			
		});
		t2.start();
	}

}
/*
methodA=0
methodA=1
methodA=2
methodA=3
methodA=4
methodB=0
methodB=1
methodB=2
methodB=3
methodB=4
*/

有结果可以看出,static修饰的属于类,所以都是作用在同一个类锁,所以会同步,是串行,

案例九

synchronized的对象锁和static静态的synchronized的类锁

public class SynchronizedTest5 {
	public synchronized  void methodA(){
		
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodA="+i);
				Thread.sleep(1000);
			}
			
			}catch (Exception e){
			e.printStackTrace();
			}
		
	}
	public void methodB(){
		synchronized (SynchronizedTest5.class){
			try{
			for(int i=0;i<5;i++){
				System.out.println("methodB="+i);
				Thread.sleep(1000);
			}
			
		}catch (Exception e){
			e.printStackTrace();
		}
		}
		
	}
	public static void main(String[] args) {
		SynchronizedTest5 test1 =new SynchronizedTest5();
		
		Thread t1 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodA();
				
			}
			
		});
		t1.start();
		Thread t2 =new Thread(new Runnable(){

			@Override
			public void run() {
				test1.methodB();
				
			}
			
		});
		t2.start();
	}

}
/*实验结果
methodA=0
methodB=0
methodB=1
methodA=1
methodA=2
methodB=2
methodA=3
methodB=3
methodA=4
methodB=4
*/

由结果可以看出,synchronized修饰的属于对象锁而static synchronized的属于类是两个不同的锁,所以是异步的,并行运行

总结:

多个线程,在用同一个对象,调用有synchronized关键字修饰的方法或代码块时,我们要注意,这把锁是给哪个对象,(这个对象属于方法的),被锁住的对象需要在解锁后才可以被其他带锁的方法或代码块使用,此时是串行运行,但是如果其他线程中该对象调用的是其他不带synchronized修饰的方法或代码块时,此时是并发运行的.
synchronized修饰类时有两种形式static synchronizedsynchronized(类名.class),此时,对象是属于类的,在遇到只有synchronized修饰的方法时,两者对象的归属不同所以是可以并发运行的
String作为锁对象时要慎用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值