sycchronized 同步锁

感谢 java synchronized详解


Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞,阻塞的意思就是不仅这个方法不能执行,这之后的方法也不能执行。

     四、这三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

     五、以上规则对其它对象锁同样适用.

synchronized可以同时修饰静态方法和实例方法,但 类锁和对象锁是两个不一样的锁,控制着不同的区域,它们是互不干扰的。同样,线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的


代码举例:

1,   当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块

package com.tjove.main;

public class ThreadDemo {

	public static void main(String[] args) {
		Runnable runnable=new ThreadA();
		Runnable runnable1=new ThreadA();
		Thread t1=new Thread(runnable);
		Thread t2=new Thread(runnable);
		t1.setName("A");
		t2.setName("B");

//		t1.setPriority(Thread.MIN_PRIORITY);
//		t2.setPriority(Thread.MAX_PRIORITY);
		
		t1.start();
		t2.start();

	}

}
public class ThreadA implements Runnable{
	int i=10;
	@Override
	public void run() {
			while (i>0) {
//				synchronized (this) {
				
					System.out.println(Thread.currentThread().getName()+i);
					i--;
					Thread.yield();
//			}
		}
		Thread.yield();
	}		
}


把注释去掉,使用代码块后运行结果如下:

B线程必须等到A线程执行完代码块中的方法之后,才有可能执行,也就是说,A、B线程的i值不会像之前那样产生重复。

如果代码块所在的位置是这样:

	synchronized (this) {
			while (i>0) {
				
					System.out.println(Thread.currentThread().getName()+i);
					i--;
					Thread.yield();
			}
		}
那么B线程会等到A线程把while循环全部走完再执行,但是这个时候i=0,已经不满足循环条件了,所以B线程也不会执行,运行结果如下:


2、当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

class Test{
	 void exe() {
		int i=10;
		
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
		}
	}
	 void exe1() {
		int i=10;
		synchronized (this) {
			
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
			}
		}
	}
}
	public static void main(String[] args) {
		final Test test=new Test();
		Thread t1=new Thread(new Runnable() {
			
			@Override
			public void run() {
				test.exe1();
				
			}
		});
		Thread t2=new Thread(new Runnable() {
			
			@Override
			public void run() {
				test.exe();
				
			}
		});
		
		t1.setName("A");
		t2.setName("B");

		t1.start();
		t2.start();

	}
运行结果:

3、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

方法体修改如下:exe()方法加上同步锁

class Test{
	<strong>synchronized</strong> void exe() {
		int i=10;
		
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
		}
	}
	 void exe1() {
		int i=10;
		<strong>synchronized (this)</strong> {
			
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
			}
		}
	}
}
运行结果如下:

虽然执行的是不同方法,但A、B公用同一个对象锁,A释放锁之后B才能执行exe1()方法

如果把test改成这样: exe方法锁的对象是调用这个方法的对象(test),exe1锁的对象是object,锁的对象不一样,所以不能实现同步的作用

class Test{
	<strong>synchronized</strong> void exe() {
		int i=10;
		
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
		}
	}
	 void exe1() {
		int i=10;
		<strong>Object object=new Object();</strong>
		synchronized (object) {
			
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
			}
		}
	}
}
结果如下:

如果把test改成这样: exe方法锁的对象是调用这个方法的Test的某个对象,exe1锁的对象是Test这个类,锁的对象不一样,所以不能实现同步的作用

class Test{
	<strong>synchronized  void exe()</strong> {//锁的是 调用这个方法的对象
		int i=10;
		
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
		}
	}
	 void exe1() {
		int i=10;
		<strong>synchronized (Test.class)</strong> {//锁的是 Test这个类 
			
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
			}
		}
	}
}
结果如下:

如果把test改成这样: exe方法锁的对象是调用这个方法的Test的类,exe1锁的对象也是Test这个类,锁的对象一样,能实现同步的作用.

class Test{
	<strong>synchronized static void exe(</strong>) {
		int i=10;
		
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
		}
	}
	 void exe1() {
		int i=10;
		<strong>synchronized (Test.class)</strong> {
			
			while (i>0) {
				
				System.out.println(Thread.currentThread().getName()+i);
				i--;
			}
		}
	}
}
结果如下:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值