码迷,mamicode.com
首页 > 编程语言 > 详细

Java多线程Thread的安全及解决机制

时间:2018-02-05 23:27:41      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:过程   ring   out   rgs   extend   while   system   star   表示   

        线程安全问题存在的原因?由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在了安全问题

package com.atguigu.java;

public class TestWindow1 {
    public static void main(String[] args) {
        Window w = new Window();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t1.start();
        t2.start();
    }
}

class Window implements Runnable {
    int ticket = 50;

    public void run() {
        while (true) {
            if (ticket > 0) {
                try {
                    Thread.currentThread().sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "售票,票号为:"
                        + ticket--);
            } else {
                break;
            }
        }
    }
}
运行结果中的一种:

窗口1售票,票号为:50
窗口2售票,票号为:49
窗口1售票,票号为:48
窗口2售票,票号为:47
窗口2售票,票号为:46
窗口1售票,票号为:45
窗口2售票,票号为:43
窗口1售票,票号为:44
窗口1售票,票号为:42
窗口2售票,票号为:41
窗口2售票,票号为:40
窗口1售票,票号为:39
窗口2售票,票号为:38
窗口1售票,票号为:38
窗口2售票,票号为:37
窗口1售票,票号为:36
窗口1售票,票号为:34
窗口2售票,票号为:35
窗口2售票,票号为:33
窗口1售票,票号为:32
窗口2售票,票号为:31
窗口1售票,票号为:31
窗口2售票,票号为:30
窗口1售票,票号为:29
窗口2售票,票号为:28
窗口1售票,票号为:27
窗口2售票,票号为:26
窗口1售票,票号为:26
窗口1售票,票号为:25
窗口2售票,票号为:24
窗口1售票,票号为:23
窗口2售票,票号为:22
窗口1售票,票号为:21
窗口2售票,票号为:20
窗口1售票,票号为:19
窗口2售票,票号为:19
窗口1售票,票号为:18
窗口2售票,票号为:17
窗口2售票,票号为:15
窗口1售票,票号为:16
窗口1售票,票号为:14
窗口2售票,票号为:13
窗口1售票,票号为:12
窗口2售票,票号为:11
窗口1售票,票号为:10
窗口2售票,票号为:9
窗口2售票,票号为:8
窗口1售票,票号为:8
窗口2售票,票号为:7
窗口1售票,票号为:6
窗口1售票,票号为:4
窗口2售票,票号为:5
窗口2售票,票号为:3
窗口1售票,票号为:2
窗口2售票,票号为:0
窗口1售票,票号为:1

可以发现运行结果中存在重票及票数为0的情况

      如何来解决线程的安全问题?必须让一个线程操作共享数据完毕以后,其它线程才有机会参与共享数据的操作

Java实现线程的安全方式一:synchronized关键字,线程的同步

       1)同步代码块          

package com.atguigu.java;
//实现Runnable接口
class Window implements Runnable { int ticket = 50;// 共享数据 public void run() { while (true) {
//注:在实现的方式中,考虑同步的话,可以使用this来充当锁。但是在继承的方式中,慎用this!
synchronized (this) {//this表示当前对象,本题中即为w if (ticket > 0) { try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "售票,票号为:" + ticket--); } } } } } public class TestWindow { public static void main(String[] args) { Window w = new Window(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); t1.setName("窗口1"); t2.setName("窗口2"); t1.start(); t2.start(); } }
package com.atguigu.java;
//继承Thread类
class Window extends Thread {
    static int ticket = 100;
    static Object obj = new Object();

    public void run() {
        while (true) {
            synchronized (obj) {
                if (ticket > 0) {
                    try {
                        Thread.currentThread().sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            + "售票,票号为:" + ticket--);
                }
            }
        }
    }    
}

public class TestWindow {
    public static void main(String[] args) {
        Window w1 = new Window();
        Window w2 = new Window();
        w1.setName("窗口1");
        w2.setName("窗口2");
        w1.start();
        w2.start();
    }
}

       2)同步方法

package com.atguigu.java;
class
Window implements Runnable { int ticket = 100;// 共享数据 public void run() { while (true) { show(); } } public synchronized void show() { if (ticket > 0) { try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "售票,票号为:" + ticket--); } } } public class TestWindow { public static void main(String[] args) { Window w = new Window(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); t1.setName("窗口1"); t2.setName("窗口2"); t1.start(); t2.start(); } }

 Java实现线程的安全方式二:Lock

package com.yyx.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
     public static void main(String[] args) {
          Window w = new Window();
          Thread t1 = new Thread(w);
          Thread t2 = new Thread(w);
          t1.setName("窗口1");
          t2.setName("窗口2");
          t1.start();
          t2.start();
      }
}

//实现Runnable接口
class Window implements Runnable {
  int ticket = 100;// 共享数据
  Lock lock=new ReentrantLock();
  public void run() {
      while (true) {
             try {
                 lock.lock();
                 if (ticket > 0) {
                     try {
                         Thread.currentThread().sleep(10);
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
                     System.out.println(Thread.currentThread().getName()
                             + "售票,票号为:" + ticket--);
                 }
            } catch (Exception ex) {
                
            }finally{
                lock.unlock();
            }
              
      }
  }
}

 

Java多线程Thread的安全及解决机制

标签:过程   ring   out   rgs   extend   while   system   star   表示   

原文地址:https://www.cnblogs.com/guhun/p/8414046.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!