浅谈Java多线程的同步问题

如题所述

第1个回答  2022-09-28

  多线程的同步依靠的是对象锁机制 synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问

  下面以一个简单的实例来进行对比分析 实例要完成的工作非常简单 就是创建 个线程 每个线程都打印从 到 这 个数字 我们希望线程之间不会出现交叉乱序打印 而是顺序地打印

  先来看第一段代码 这里我们在run()方法中加入了synchronized关键字 希望能对run方法进行互斥访问 但结果并不如我们希望那样 这是因为这里synchronized锁住的是this对象 即当前运行线程对象本身 代码中创建了 个线程 而每个线程都持有this对象的对象锁 这不能实现线程的同步

  代码    package vista;    class MyThread implements java lang Runnable {     private int threadId;

  public MyThread(int id) {      this threadId = id;     }

  @Override     public synchronized void run() {      for (int i = ; i < ; ++i) {       System out println( Thread ID: + this threadId + : + i);      }     }    }

  public class ThreadDemo {     /**      * @param args      * @throws InterruptedException      */     public static void main(String[] args) throws InterruptedException {      for (int i = ; i < ; ++i) {       new Thread(new MyThread(i)) start();       Thread sleep( );      }     }    }

  从上述代码段可以得知 要想实现线程的同步 则这些线程必须去竞争一个唯一的共享的对象锁

  基于这种思想 我们将第一段代码修改如下所示 在创建启动线程之前 先创建一个线程之间竞争使用的Object对象 然后将这个Object对象的引用传递给每一个线程对象的lock成员变量 这样一来 每个线程的lock成员都指向同一个Object对象 我们在run方法中 对lock对象使用synchronzied块进行局部封锁 这样就可以让线程去竞争这个唯一的共享的对象锁 从而实现同步

  代码    package vista;

  class MyThread implements java lang Runnable {     private int threadId;     private Object lock;

  public MyThread(int id Object obj) {      this threadId = id;      this lock = obj;     }

  @Override     public void run() {      synchronized (lock) {       for (int i = ; i < ; ++i) {        System out println( Thread ID: + this threadId + : + i);       }      }     }    }

  public class ThreadDemo {     /**      * @param args      * @throws InterruptedException      */     public static void main(String[] args) throws InterruptedException {      Object obj = new Object();      for (int i = ; i < ; ++i) {       new Thread(new MyThread(i obj)) start();       Thread sleep( );      }     }    }

  从第二段代码可知 同步的关键是多个线程对象竞争同一个共享资源即可 上面的代码中是通过外部创建共享资源 然后传递到线程中来实现 我们也可以利用类成员变量被所有类的实例所共享这一特性 因此可以将lock用静态成员对象来实现 代码如下所示

  代码    package vista;

  class MyThread implements java lang Runnable {     private int threadId;     private static Object lock = new Object();

  public MyThread(int id) {      this threadId = id;     }

  @Override     public void run() {      synchronized (lock) {       for (int i = ; i < ; ++i) {        System out println( Thread ID: + this threadId + : + i);       }      }     }    }

  public class ThreadDemo {     /**      * @param args      * @throws InterruptedException      */     public static void main(String[] args) throws InterruptedException {      for (int i = ; i < ; ++i) {       new Thread(new MyThread(i)) start();       Thread sleep( );      }     }    }

  再来看第一段代码 实例方法中加入sychronized关键字封锁的是this对象本身 而在静态方法中加入sychronized关键字封锁的就是类本身 静态方法是所有类实例对象所共享的 因此线程对象在访问此静态方法时是互斥访问的 从而可以实现线程的同步 代码如下所示

  代码    package vista;

  class MyThread implements java lang Runnable {     private int threadId;

  public MyThread(int id) {      this threadId = id;     }

  @Override     public void run() {      taskHandler(this threadId);     }

  private static synchronized void taskHandler(int threadId) {      for (int i = ; i < ; ++i) {       System out println( Thread ID: + threadId + : + i);      }     }    }

lishixinzhi/Article/program/Java/gj/201311/27441

相似回答