1.修饰在方法上,多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)
public synchronized void obj3() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
2.修饰代码块,这个this就是指当前对象(类的实例),多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)
public void obj2() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
3.修饰代码块,这个str就是指String对象,多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)
public void obj2() {
String str=new String("lock");//在方法体内,调用一次就实例化一次,多线程访问不会阻塞,因为不是同一个对象,锁是不同的
synchronized (str) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public static void main(String[] args) throws InterruptedException {
test test=new test();
new Thread(new Runnable() {
@Override
public void run() {
test.obj2();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
test.obj2();
}
}).start();
}
//两个方法之间交替执行 没有阻塞
Thread-0 : 4
Thread-1 : 4
Thread-1 : 3
Thread-0 : 3
Thread-1 : 2
Thread-0 : 2
Thread-1 : 1
Thread-0 : 1
Thread-0 : 0
Thread-1 : 0
共用一个对象,多线程调用obj2同步方法,因为使用的是一个对象锁,会阻塞。
String str=new String("lock"); //对象放在方法外,调用方法的时候不会新创建一个对象。
public void obj2() {
synchronized (str) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
Thread-0 : 4
Thread-0 : 3
Thread-0 : 2
Thread-0 : 1
Thread-0 : 0
Thread-1 : 4
Thread-1 : 3
Thread-1 : 2
Thread-1 : 1
Thread-1 : 0
1.Synchronized修饰静态的方法
public static synchronized void obj3() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
2.synchronized (test.class) ,锁的对象是test.class,即test类的锁。
public void obj1() {
synchronized (test.class) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
那么问题来了:在一个类中有两方法,分别用synchronized 修饰的静态方法(类锁)和非静态方法(对象锁)。多线程访问两个方法的时候,线程会不会阻塞?
public static synchronized void obj3() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public synchronized void obj4() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
答案是???
Thread-0 : 4
Thread-1 : 4
Thread-0 : 3
Thread-1 : 3
Thread-1 : 2
Thread-0 : 2
Thread-1 : 1
Thread-0 : 1
Thread-1 : 0
Thread-0 : 0
到这么我们应该知道了:
1,要满足方法同步(或者代码块同步)就必须保证多线程访问的是同一个对象(在java内存中的地址是否相同)。
2,类锁和对象锁同时存在时,多线程访问时不会阻塞,因为他们不是一个锁。
感谢原作者:Synchronized方法锁、对象锁、类锁区别 - 不懂就查 - 博客园