多线程----通俗易懂(第一天)

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();
	}
	
}

执行上述代码块,发现在同步代码块执行的时候.非同步方法还是可以执行的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章