synchronized的应用方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wueryan/article/details/86501041

synchronized的三种应用方式

(1)修饰实例方法
(2)修饰静态方法
(3)修饰代码块

修饰实例方法

/***
*  代码1-1
*/
public class SynDemo implements Runnable{
         static int i=0;
         public synchronized void increase(){
                  i++;
        }
        public void run(){
              for(int j=0;j<1000000;j++){
                     this.increase();
              }
        }

		public static void main(String[] args){
			SynDemo demo = new SynDemo();
			Thread t1 = new Thread(demo);
			Thread t2 = new Thread(demo);
			t1.start();
			t2.start();
			t1.join();
			t2.join();
		}
}

在代码1-1中,我们开启了两个线程对全局变量i进行了加1的操作。在这个过程中,为了保证线程安全,由于我们对实例方法increase()进行了synchronized的修饰。此时线程会对对象锁进行竞争获取,先获取到锁的线程禁止其他线程调用increase()方法。
对于同一个对象来说,只有一个锁,一旦被某个线程竞争获取到锁了,其他线程就无法获取该对象的锁了。值得注意的是,同一个类的实例化对象如果是不同的,比如以下代码1-2的例子,那么对于线程来说,其实是获取了不同的对象锁,自然而然的对于increase()就会分别执行。

/***
*  代码1-2
*/
public class SynDemo implements Runnable{
         static int i=0;
         public synchronized void increase(){
                  i++;
        }
        public void run(){
              for(int j=0;j<1000000;j++){
                     this.increase();
              }
        }

		public static void main(String[] args){
			SynDemo demo1 = new SynDemo();
			SynDemo demo2 = new SynDemo();
			Thread t1 = new Thread(demo1);
			Thread t2 = new Thread(demo2);
			t1.start();
			t2.start();
			t1.join();
			t2.join();
		}
}

修饰静态方法

public class synDemo2 implements Runnable{
           static int i =0 ;
           public static synchronized void increase(){
                 i++;
           }
           public synchronized void increase2(){
           		i++;
           }
           public void run(){
           		 for (int j=0;j<1000000;j++){
           		 		increase();
           		 }
           }

			public static void main(String[] args){
			     SynDemo2 demo1 = new SynDemo2();
			     SynDemo2 demo2 = new SynDemo2();
			     Thread t1 = new Thread(demo1);
			     Thread t2 = new Thread(demo2);
			      t1.start();
			      t2.start();
			      t1.join();
			      t2.join();
		}
}

修饰静态方法时,此时会锁当前类的class对象锁。这里值得注意的时,类的锁和实例对象的锁并不是同一个锁。因此在demo中,我们可以看到同样是用synchronized修饰increase()和increase2()方法,但是由于实例的锁和类的class对象锁并不会产生互斥。这里在不同线程进行操作时,可能会产生线程安全问题。

synchronized同步代码块

public class SynDemo3 implements Runnable{
         static SynDemo3 instance = new SynDemo3();
         static int i=0;

		public  void run(){
				synchronized(instance){
					 for(int j=0;j<1000000;j++){
					 	 i++;
					 }
				}

				
				synchronized(this){
					//do something
				}
				synchronized(SynDemo3.class){
					//do something
				}
		}
}

除了instance作为对象外,还可以用this对象或者当前类的class对象作为锁。

猜你喜欢

转载自blog.csdn.net/wueryan/article/details/86501041