使用Synchronized关键字给一个对象加锁第一种方式:synchronize代码块,锁定自己创建的对象
[Java] 纯文本查看 复制代码 public class T {
private int count = 10;
private Object o = new Object();
public void m() {
synchronized (o) {
//任何线程要执行sychronized中的代码,必须先拿到对象o的锁
//只要一个线程调用了m方法,在执行到synchronized代码块时
//必须先拿到o的锁,
count--;
System.out.println(Thread.currentThread().getName() + "count=" + count);
}
}
第二种方式:synchrinize代码块锁定this对象
[Java] 纯文本查看 复制代码 public class T {
private int count = 10;
public void m() {
//第二种写法,不用new一个Object,直接用该对象自身作为锁
synchronized (this) {
count--;
System.out.println(Thread.currentThread().getName() + "count=" + count);
}
}
第三种方式:synchronize锁定方法,锁定的也是this对象
[Java] 纯文本查看 复制代码 public class T {
private int count = 10;
public synchronized void m() {
//相当于sychronized(this){}
//注意sychronized锁定的不是代码块中的代码,而是this对象
count--;
System.out.println(Thread.currentThread().getName() + "count" + count);
}
}
使用synchronize锁定静态方法时,相当于锁定当前类的class对象(o.class)
[Java] 纯文本查看 复制代码 public class T {
private static int count = 10;
private synchronized static void m() {
//锁定静态方法
count--;
System.out.println(Thread.currentThread().getName() + "count" + count);
}
//相当于锁定当前类的class对象
private static void m2() {
synchronized (T.class) {
count--;
System.out.println(Thread.currentThread().getName() + "count" + count);
}
}
}
一个synchronized代码块中的代码相当于一次原子操作,要么都不执行,要么全部执行,不会被其它线程打断 在同一个对象的非同步方法和同步方法可以同时执行 脏读 1.对写数据的方法加锁,但对读数据的方法不加锁 写数据的方法中,除了写数据,可能还有其它的业务代码。如果写的过程中执行读数据的方法,可能读出还未进行写入的数据。 2.是否允许脏读要看具体情况 synchronized获得的锁是可重入的。 一个线程已经拥有某个对象的锁,再次申请时仍会获得该对象的锁。 一个线程获得了子类对象的锁,可以调用父类的同步方法。因为synchronized锁定的是this对象,所以调用两个方法锁定的是同一个对象,即子类对象。 同步方法在执行时,如果出现异常,将会释放锁。
|