Java基础之线程安全问题

线程安全问题

线程安全为标题

在java程序中,若是有多个线程同时运行,而且同时执行同一段代码,若是程序每次运行的结果和单线程运行的结果是同样的,并且其余变量的值也和预期是同样的,那么这段代码就是线程安全的。java

可是在多线程操做中也可能会有一些线程安全的问题发生。web

以卖票事例做为说明,有100张票往外售卖,售完结束。安全

public class Tickets implements Runnable{
   //初始化票数
   private   int ticket=100;

   @Override
   public void run() {
       //卖票
       while (true){
         
               if(ticket>0){
                   try {
                       Thread.sleep(50);
                  } catch (InterruptedException e) {
                       e.printStackTrace();
                  }
                   System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
              }
      }
  }
}

 

public class TicketsTest {
   public static void main(String[] args) {
       //声明变量
       Tickets tickets = new Tickets();

       //建立三个线程(窗口)
       Thread t1 = new Thread(tickets,"窗口1");
       Thread t2 = new Thread(tickets,"窗口2");
       Thread t3 = new Thread(tickets,"窗口3");

       //三个窗口同时买票
       t1.start();
       t2.start();
       t3.start();
  }

}

 

可是在运行结果中会发生如下这种状况:票已经卖出,可是总数没有减小;或者票已经售空,仍然在减票的状况多线程

窗口3正在卖:100
窗口1正在卖:99
窗口2正在卖:100
窗口1正在卖:98
.......
窗口2正在卖:4
窗口1正在卖:2
窗口3正在卖:1
窗口2正在卖:1
窗口1正在卖:1

这类问题就称做线程安全问题,为了解决这个问题,能够采起一些线程同步的措施并发

线程同步

当咱们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操做,就容易出现线程安全问题。ide

为了解决并发问题(线程同步问题),也就是多线程并发访问同一个资源,对这个资源进行写操做的问题,java中提供了线程同步(synchronized)来解决这个问题。atom

解决线程同步的方法:spa

  • 方法1:同步代码块线程

    • 同步代码块:synchronized加在代码块上,格式以下code

    synchronized (lock){
       //须要同步的代码块
      ....
    }

     

  • 方法2:同步锁

    • 对象的同步锁只是一个概念,能够想象为在对象上标记了一个锁.

      1. 锁对象 能够是任意类型。

      2. 多个线程对象 要使用同一把锁。

  • 方法3:同步方法

    • 在方法进行同步,格式以下:

     public synchronized void method(){
           //须要同步的代码块
          ......
      }
Lock锁

java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更普遍的锁定操做,同步代码块/同步方法具备的功能Lock都有,除此以外更强大,更体现面向对象。Lock锁也称同步锁,加锁与释放锁方法化了,以下:public void lock() :加同步锁。public void unlock() :释放同步锁。使用以下:

public class Tickets implements Runnable{
   //初始化票数
   private   int ticket=100;
  Lock lock = new ReentrantLock();
   @Override
   public void run() {
       //卖票
       while (true){
               lock.lock();
               if(ticket>0){
                   try {
                       Thread.sleep(50);
                  } catch (InterruptedException e) {
                       e.printStackTrace();
                  }
                   System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
              }
               lock.unlock();
      }
  }
}

 

线程安全问题

线程安全为标题

在java程序中,若是有多个线程同时运行,而且同时执行同一段代码,若是程序每次运行的结果和单线程运行的结果是同样的,并且其余变量的值也和预期是同样的,那么这段代码就是线程安全的。

可是在多线程操做中也可能会有一些线程安全的问题发生。

以卖票事例做为说明,有100张票往外售卖,售完结束。

public class Tickets implements Runnable{
   //初始化票数
   private   int ticket=100;

   @Override
   public void run() {
       //卖票
       while (true){
         
               if(ticket>0){
                   try {
                       Thread.sleep(50);
                  } catch (InterruptedException e) {
                       e.printStackTrace();
                  }
                   System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
              }
      }
  }
}

 

public class TicketsTest {
   public static void main(String[] args) {
       //声明变量
       Tickets tickets = new Tickets();

       //建立三个线程(窗口)
       Thread t1 = new Thread(tickets,"窗口1");
       Thread t2 = new Thread(tickets,"窗口2");
       Thread t3 = new Thread(tickets,"窗口3");

       //三个窗口同时买票
       t1.start();
       t2.start();
       t3.start();
  }

}

 

可是在运行结果中会发生如下这种状况:票已经卖出,可是总数没有减小;或者票已经售空,仍然在减票的状况

窗口3正在卖:100
窗口1正在卖:99
窗口2正在卖:100
窗口1正在卖:98
.......
窗口2正在卖:4
窗口1正在卖:2
窗口3正在卖:1
窗口2正在卖:1
窗口1正在卖:1

这类问题就称做线程安全问题,为了解决这个问题,能够采起一些线程同步的措施

线程同步

当咱们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操做,就容易出现线程安全问题。

为了解决并发问题(线程同步问题),也就是多线程并发访问同一个资源,对这个资源进行写操做的问题,java中提供了线程同步(synchronized)来解决这个问题。

解决线程同步的方法:

  • 方法1:同步代码块

    • 同步代码块:synchronized加在代码块上,格式以下

    synchronized (lock){
       //须要同步的代码块
      ....
    }

     

  • 方法2:同步锁

    • 对象的同步锁只是一个概念,能够想象为在对象上标记了一个锁.

      1. 锁对象 能够是任意类型。

      2. 多个线程对象 要使用同一把锁。

  • 方法3:同步方法

    • 在方法进行同步,格式以下:

     public synchronized void method(){
           //须要同步的代码块
          ......
      }
Lock锁

java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更普遍的锁定操做,同步代码块/同步方法具备的功能Lock都有,除此以外更强大,更体现面向对象。Lock锁也称同步锁,加锁与释放锁方法化了,以下:public void lock() :加同步锁。public void unlock() :释放同步锁。使用以下:

public class Tickets implements Runnable{
   //初始化票数
   private   int ticket=100;
  Lock lock = new ReentrantLock();
   @Override
   public void run() {
       //卖票
       while (true){
               lock.lock();
               if(ticket>0){
                   try {
                       Thread.sleep(50);
                  } catch (InterruptedException e) {
                       e.printStackTrace();
                  }
                   System.out.println(Thread.currentThread().getName()+"正在卖:"+ticket--);
              }
               lock.unlock();
      }
  }
}
相关文章
相关标签/搜索