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--;
}
}
}
}
结果如下: