单例模式 多线程并发控制

单例模式应用场景之一: 确保共享的数据,共享的操作,在多线程下,线程安全。其实现方式是:控制资源的使用,通过线程同步来控制资源的并发访问;

疑问:一直都不理解为什么可以做到,不使用单例,为什么又做不到?

 

一、设计测试场景:

1、单例测试场景

单例类:

public class ShareResourceSingleton {

       private static ShareResourceSingleton instance = new ShareResourceSingleton();

       private ShareResourceSingleton() {

       }

       public static ShareResourceSingleton getInstance() {

              return instance;

       }

       public synchronized void testShareResourcePrototype() {

              System.out.println("testShareResourcePrototype" + Thread.currentThread().getName());

              try {

                     Thread.currentThread().sleep(5500);

              } catch (InterruptedException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

              }

              System.out.println("testShareResourcePrototype" + Thread.currentThread().getName() + "sleep over");

       }

}

 

测式主类

public class TestThread {

       public static void main(String[] args) {        

              Thread t1 = new Thread1();

              Thread t2 = new Thread1();

              t1.start();

              t2.start();

       }

}

 

 

 

线程1

public class Thread1 extends Thread{

       public void run(){

              /*ShareResourcePrototype shareResourcePrototype = new ShareResourcePrototype();

              shareResourcePrototype.testShareResourcePrototype();*/

              ShareResourceSingleton shareResourceSingleton = ShareResourceSingleton.getInstance();

              shareResourceSingleton.testShareResourcePrototype();

       }

}

 

输出:

testShareResourcePrototypeThread-0

testShareResourcePrototypeThread-0sleep over

testShareResourcePrototypeThread-1

testShareResourcePrototypeThread-1sleep over

 

2、多例测试场景

多例类:

public class ShareResourcePrototype {

       private int i = 0;

       public synchronized void testShareResourcePrototype() {

              System.out.println("testShareResourcePrototype" + Thread.currentThread().getName());

              try {

                     Thread.currentThread().sleep(5500);

              } catch (InterruptedException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

              }

              System.out.println("testShareResourcePrototype" + Thread.currentThread().getName() + "sleep over");

       }

}

 

 

线程1

public class Thread1 extends Thread{

       public void run(){

              ShareResourcePrototype shareResourcePrototype = new ShareResourcePrototype();

              shareResourcePrototype.testShareResourcePrototype();

       /*     ShareResourceSingleton shareResourceSingleton = ShareResourceSingleton.getInstance();

              shareResourceSingleton.testShareResourcePrototype();*/

       }

}

 

输出:

testShareResourcePrototypeThread-0

testShareResourcePrototypeThread-1

testShareResourcePrototypeThread-0sleep over

testShareResourcePrototypeThread-1sleep over

 

 

二、结论:

1、以上输出说明,在使用单例时,同步代码块仅能被一个线程访问,直到线程执行完同步代码块,释放锁。其它线程才能进入此代码块。这样就达到了控制并发访问的目的,实现了线程安全

所以使用单例+线程同步 ,可以满足一些特定的场景,比如:打印,文件访问等需要全局控制并发访问需求

2、使用多例时,同步代码块没有起到互斥的作用,可以被多线程同时访问

 

回答之前的疑问:

不理解,并不是不理解单例模式,而是不理解synchronized 这个的作用。

 synchronized 只会锁定调用其同步方法的那个对象,意思是,多线程只有使用同一个对象(实例)时,才可以达到同步方法互斥访问的效果

你可能感兴趣的:(设计模式释疑)