【多线程 - 08、线程同步 synchronized】

什么情况下会产生线程安全问题

同时满足以下两个条件时:

  • 多个线程在操作共享的数据。
  • 操作共享数据的线程代码有多条。

当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。

例子:四个线程卖100张票

public class ThreadTest {
    public static void main(String[] args) {
        synchronizeThread st = new synchronizeThread();
        new Thread(st,"1").start();
        new Thread(st,"2").start();
        new Thread(st,"3").start();
        new Thread(st,"4").start();
    }
}
class synchronizeThread implements Runnable {
    private int ticketNumber = 100;
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (ticketNumber > 0) {
                System.out.println("线程【" + Thread.currentThread().getName() + "】卖出了一张票,现在剩余了【" + ticketNumber + "】张票");
                ticketNumber--;
            } else {
                break;
            }
        }
    }
}

运行结果:发现会有多个线程卖同一张票的情况发生,这就是线程安全问题。

解决这样的问题就是线程同步的方式来实现。

线程同步

同步就是协同步调,按预定的先后次序进行运行。这里的同步千万不要理解成那个同时进行,应是指协同、协助、互相配合。线程同步是指多线程通过特定的设置来控制线程之间`的执行顺序(即所谓的同步)也可以说是在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间是各自运行各自的

synchronized 同步代码块

即用synchronized关键字修饰的语句块。

被该关键字修饰的语句块会自动被加上内置锁,被保护的语句代码所在的线程要执行,需要获得内置锁,否则就处于阻塞状态。

代码

synchronized(object){ 
}

括号里的这个对象可以是任意对象,这个对象一般称为同步锁。

同步的前提

同步中必须有多个线程并使用同一个锁。

同步的好处

解决了线程的安全问题。

注意

同步是一种高开销的操作,因此应该尽量减少同步的内容。 通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。

例子:四个线程卖100张票

package cn.hyl.test1;

public class ThreadTest {
    public static void main(String[] args) {
        synchronizeThread st = new synchronizeThread();
        new Thread(st,"1").start();
        new Thread(st,"2").start();
        new Thread(st,"3").start();
        new Thread(st,"4").start();
    }
}
class synchronizeThread implements Runnable {
    private Integer ticketNumber = 100;
    private Object object = new Object();
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
           synchronized (ticketNumber){
               if (ticketNumber > 0) {
                   System.out.println("线程【" + Thread.currentThread().getName() + "】卖出了一张票,现在剩余了【" + ticketNumber + "】张票");
                   ticketNumber--;
               } else {
                   break;
               }
           }
        }
    }
}

synchronized同步方法

即用synchronized关键字修饰的方法。

由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

代码

public synchronized void save(){}

注意

  • 对于普通同步方法,锁是当前实例对象。
  • 对于静态同步方法,锁是当前类的Class对象。
  • 对于同步方法块,锁是Synchonized括号里配置的对象。

你可能感兴趣的:(多线程,java,jvm,android)