您的位置:首页 > 编程语言 > Java开发

Java高并发程序-Chapter2 Java并行程序基础 (第八讲)线程组 、守护线程、线程优先级

2018-03-27 11:38 706 查看
线程安全的概念与 synchronized
1. 指定加锁对象
指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁
public class AccountSyncByInstance implements Runnable {

  public void run() {

    for (int j = 0; j < 100000; j++) {

     synchronized (this) {
       i++;
     }
     
     
    }

  }

  public int getSummary() {

    return i;
  }

  private int i = 0;

  public static void main(String[] args) throws InterruptedException {

    AccountSyncByInstance instance = new AccountSyncByInstance();

    Thread t1 = new Thread(instance);
    Thread t2 = new Thread(instance);
    Thread t3 = new Thread(instance);
    
    t1.start();
    t2.start();
    t3.start();
    
    t1.join();
    t2.join();
    t3.join();
    
    System.out.println(instance.getSummary());

  }
}
2. 直接作用于实例方法
相当于对当前实例加锁,进入同步代码前要获得当前实例的锁
public class AccountSyncByMethod implements Runnable {

  public void run() {

    for (int j = 0; j < 100000; j++) {

     synchronized (this) {
       
       increase();
     }

    }

  }

  private synchronized void increase() {
    i++;
  }

  public int getSummary() {

    return i;
  }

  private int i = 0;

  public static void main(String[] args) throws InterruptedException {

    AccountSyncByMethod instance = new AccountSyncByMethod();

    Thread t1 = new Thread(instance);
    Thread t2 = new Thread(instance);
    Thread t3 = new Thread(instance);

    t1.start();
    t2.start();
    t3.start();

    t1.join();
    t2.join();
    t3.join();

    System.out.println(instance.getSummary());

  }
}
3. 直接作用于静态方法
直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁

一种错误的同步方式如下:
public class AccountSyncByBad implements Runnable {

  public void run() {

    for (int j = 0; j < 100000; j++) {

     synchronized (this) {

       increase();
     }

    }

  }

  private synchronized void increase() {
    i++;
  }

  public int getSummary() {

    return i;
  }

  private static int i = 0;

  public static void main(String[] args) throws InterruptedException {

    Thread t1 = new Thread(new AccountSyncByBad());
    Thread t2 = new Thread(new AccountSyncByBad());
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(i);

  }
}
虽然在第3行的 Increase()方法中,申明这是一个同步方法。

但很不幸的是,执行这段代码的两个线程都指向了不同的 Runnable实例。
   Thread t1 = new Thread(new AccountSyncByBad());
   Thread t2 = new Thread(new AccountSyncByBad());由第13、14行可以看到,这两个线程的 Runnable实例并不是同一个对象。
因此,线程t1会在进入同步方法前加锁自己的 Runnable实例,而线程t2也关注于自己的对象锁。
换言之,这两个线程使用的是两把不同的锁。因此,线程安全是无法保证的。

但我们只要简单地修改上述代码,就能使其正确执行。
那就是使用 synchronized的第三种用法,将其作用于静态方法private static synchronized void increase() {
    i++;
}除了用于线程同步、确保线程安全外, synchronized还可以保证线程间的可见性和有序性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并发编程