多线程同步锁synchronized(对象锁与全局锁)总结

1.synchronized同步锁的引入

/*
 * 非线程安全
 * */
//多个线程共同访问一个对象中的实例变量,则会出现"非线程安全"问题
class MyRunnable1 implements Runnable{
	private int num = 10;
	public void run() {
		try {
			if(num > 0) {
				System.out.println(""+Thread.currentThread().getName()+"开始"+",num= "+num--);
				Thread.sleep(1000);
				System.out.println(""+Thread.currentThread().getName()+"结束");
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}public class Test5_5{
	public static void main(String[] args) {
		MyRunnable1 myRunnable1 =  new MyRunnable1();
		Thread thread1 = new Thread(myRunnable1,"线程1");
		Thread thread2 = new Thread(myRunnable1,"线程2");
		thread1.start();
		thread2.start();
	}
}

                          

上例说明两个线程同时访问一个没有同步的方法,如果两个线程同时操作业务对象中的实例变量,则会出现“线程不安全”问题。

由此我们引入synchronized关键字来实现同步问题:

Java中使用synchronized关键字控制线程同步,控制synchronized代码段不被多个线程同时执行,synchronized即可以使用在方法上也可以使用在代码块中。

2. 对象锁

1)synchronized方法(对当前对象进行加锁)

若我们对如上代码进行修改,在run()方法上加入synchronized关键字使其变为同步方法。

/*
 * 同步方法
 * */
class MyRunnable1 implements Runnable{
	private int num = 10;
	public void run() {
		this.print();
	}

	public synchronized void print() {
		if(this.num > 0) {
			System.out.println(""+Thread.currentThread().getName()+"开始"+",num= "+num--);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(""+Thread.currentThread().getName()+"结束");
		}
	}
}public class Test5_5{
	public static void main(String[] args) {
		MyRunnable1 myRunnable1 =  new MyRunnable1();
		Thread thread1 = new Thread(myRunnable1,"线程1");
		Thread thread2 = new Thread(myRunnable1,"线程2");
		thread1.start();
		thread2.start();
	}
}    

                       

结论:若两个线程同时访问同一个对象中的同步方法时一定是线程安全的。

2)synchronized代码块(对某一个对象进行加锁)

如果要使用同步代码块必须设置一个要锁定的对象,所以一般可以锁定当前对象:this.

/*
 * 同步代码块
 * */
class MyRunnable1 implements Runnable{
	private int num = 10;
	public void run() {
		try {
			synchronized (this) {
				if(num > 0) {
					System.out.println(""+Thread.currentThread().getName()+"开始"+",num= "+num--);
					Thread.sleep(1000);
					System.out.println(""+Thread.currentThread().getName()+"结束");
				}	
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class Test5_5{
	public static void main(String[] args) {
		MyRunnable1 myRunnable1 =  new MyRunnable1();
		Thread thread1 = new Thread(myRunnable1,"线程1");
		Thread thread2 = new Thread(myRunnable1,"线程2");
		thread1.start();
		thread2.start();
	}
}  

                          

3)synchronized锁多对象

/*
 * synchronized锁多对象
 * */
class Sync{
	public synchronized void print() {
		System.out.println("print方法开始:"+Thread.currentThread().getName());
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("print方法结束"+Thread.currentThread().getName());
	}
}
class MyThread extends Thread{
	public void run() {
		Sync sync =  new Sync();
		sync.print();
	}
}
public class Test5_5{
	public static void main(String[] args) {
		for(int i = 0; i < 3;i++) {
			Thread thread = new MyThread();
			thread.start();
		}
	}
}
                      

根据上例我们可以发现当synchronized锁多个对象时不能实现同步操作,由此可以得出关键字synchronized取得的锁都是对象锁,而不是将一段代码或者方法(函数)当作锁。哪个线程先执行带synchronized关键字的方法或synchronized代码块,哪个线程就有该方法或该代码块所持有的锁,其他线程只能呈现等待状态,前提是多个线程访问同一个对象。

只有共享资源的读写需要同步化,如果不是共享资源,那么就不需要同步化操作。

3.全局锁

实现全局锁有两种方式:

(1) synchronized关键字用在static方法上

synchronized加到static静态方法上是对Class类上锁,而synchronized加到非static方法上是给对对象上锁。Class锁可以对类的所有对象实例起作用。

/*
 * synchronized用在static方法上
 * */
class Sync{
	static public synchronized void print() {
		System.out.println("print方法开始:"+Thread.currentThread().getName());
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("print方法结束"+Thread.currentThread().getName());
	}
}
class MyThread extends Thread{
	public void run() {
		Sync.print();
	}
}
public class Test5_5{
	public static void main(String[] args) {
		for(int i = 0; i < 3;i++) {
			Thread thread = new MyThread();
			thread.start();
		}
	}
}

                     

(2) synchronized对类的Class对象进行上锁

synchronized(class)代码块的作用与synchronized static方法的作用一样。

/*
 * synchronized对类的Class对象上锁
 * */
class Sync{
	public void print() {
		synchronized (Sync.class) {
			System.out.println("print方法开始:"+Thread.currentThread().getName());
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("print方法结束"+Thread.currentThread().getName());
		}
	}
}
class MyThread extends Thread{
	public void run() {
		Sync sync =  new Sync();
		sync.print();
	}
}
public class Test5_5{
	public static void main(String[] args) {
		for(int i = 0; i < 3;i++) {
			Thread thread = new MyThread();
			thread.start();
		}
	}
}
                         


猜你喜欢

转载自blog.csdn.net/qq_40409115/article/details/80205676