public class T {
private int count = 10;
private Object o = new Object();
public void m() {
synchronized(o) { //任何线程要执行下面的代码,必须先拿到o的锁
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
}
synchronized(o) :代表任何线程要执行这行代码都必须先拿到o对象这把锁,只有持有o对象锁的线程才允许执行.如果此时第二个线程进来了,必须等到第一个线程释放了o这把锁才
public class T {
private int count = 10;
public void m() {
synchronized(this) { //任何线程要执行下面的代码,必须先拿到this的锁
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
}
synchronized(this) :指定锁定自身对象.只有获取自身对象的锁才允许进入当前方法
- 等价于如下:
public class T {
private int count = 10;
public synchronized void m() { //等同于在方法的代码执行时要synchronized(this)
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
直接将synchronized加在方法上,注意:synchronized不是锁定当前方法,而是指锁定当前对象 类似上面 synchronized(this) 的写法
public class T {
private static int count = 10;
public synchronized static void m() { //这里等同于synchronized(yxxy.c_004.T.class)
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
public static void mm() {
synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以?
count --;
}
}
}
如果synchronized锁定的是静态方法,则锁定的必须是当前类的class对象.因为静态方法是不需要对象访问的
public class T implements Runnable {
private int count = 10;
public /*synchronized*/ void run() {
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
public static void main(String[] args) {
T t = new T();
for(int i=0; i<5; i++) {
new Thread(t, "THREAD" + i).start();
}
}
}
当我们起5个线程 访问同一个对象的count值时,如果没有加锁,会导致count值为10时,可能存在多个线程同时-1 多个线程修改之后的结果还是9.要解决这个问题的话,简单的做法可以直接在方法上加一把锁.
多线程常见问题一 :同步和非同步方法是否可以同时调用?
public class T {
public synchronized void m1() {
System.out.println(Thread.currentThread().getName() + " m1 start...");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " m1 end");
}
public void m2() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " m2 ");
}
public static void main(String[] args) {
T t = new T();
new Thread(t::m1, "t1").start();
new Thread(t::m2, "t2").start();
}
}
执行上述代码块,发现在同步代码块执行的时候.非同步方法还是可以执行的.