A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Y_Y 中级黑马   /  2013-12-13 22:25  /  1346 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

我想知道线程锁到底是什么,怎么去实现的?

评分

参与人数 1黑马币 +1 收起 理由
乔兵 + 1

查看全部评分

3 个回复

倒序浏览
使用线程锁的场合

程序中经常采用多线程处理,这可以充分利用系统资源,缩短程序响应时间,改善用户体验;如果程序中只使用单线程,那么程序的速度和响应无疑会大打折扣。
但是,程序采用了多线程后,你就必须认真考虑线程调度的问题,如果调度不当,要么造成程序出错,要么造成荒谬的结果。

一个讽刺僵化体制的笑话

前苏联某官员去视察植树造林的情况,现场他看到一个人在远处挖坑,其后不远另一个人在把刚挖出的坑逐个填上,官员很费解于是询问陪同人员,当地管理人员说“负责种树的人今天病了”。
上面这个笑话如果发生在程序中就是线程调度的问题,种树这个任务有三个线程:挖坑线程,种树线程和填坑线程,后面的线程必须等前一个线程完成才能进行,而不是按时间顺序来进行,否则一旦一个线程出错就会出现上面荒谬的结果。

用线程锁来处理两个线程先后执行的情况

在程序中,和种树一样,很多任务也必须以确定的先后秩序执行,对于两个线程必须以先后秩序执行的情况,我们可以用线程锁来处理。
线程锁的大致思想是:如果线程A和线程B会执行实例的两个函数a和b,如果A必须在B之前运行,那么可以在B进入b函数时让B进入wait set,直到A执行完a函数再把B从wait set中激活。这样就保证了B必定在A之后运行,无论在之前它们的时间先后顺序是怎样的。
线程锁的代码

如右,SwingComponentLock的实例就是一个线程锁,lock函数用于锁定线程,当完成状态isCompleted为false时进入的线程会进入SwingComponentLock的实例的wait set,已完成则不会;要激活SwingComponentLock的实例的wait set中等待的线程需要执行unlock函数。

public class SwingComponentLock {
  // 是否初始化完毕
  boolean isCompleted = false;

  /**
   * 锁定线程
   */
  public synchronized void lock() {
    while (!isCompleted) {
      try {
        wait();
      } catch (Exception e) {
        e.printStackTrace();
        logger.error(e.getMessage());
      }
    }
  }

  /**
   * 解锁线程
   *
   */
  public synchronized void unlock() {
    isCompleted = true;
    notifyAll();
  }
}
回复 使用道具 举报
使用线程锁的场合

程序中经常采用多线程处理,这可以充分利用系统资源,缩短程序响应时间,改善用户体验;如果程序中只使用单线程,那么程序的速度和响应无疑会大打折扣。
但是,程序采用了多线程后,你就必须认真考虑线程调度的问题,如果调度不当,要么造成程序出错,要么造成荒谬的结果。

一个讽刺僵化体制的笑话

前苏联某官员去视察植树造林的情况,现场他看到一个人在远处挖坑,其后不远另一个人在把刚挖出的坑逐个填上,官员很费解于是询问陪同人员,当地管理人员说“负责种树的人今天病了”。
上面这个笑话如果发生在程序中就是线程调度的问题,种树这个任务有三个线程:挖坑线程,种树线程和填坑线程,后面的线程必须等前一个线程完成才能进行,而不是按时间顺序来进行,否则一旦一个线程出错就会出现上面荒谬的结果。

用线程锁来处理两个线程先后执行的情况

在程序中,和种树一样,很多任务也必须以确定的先后秩序执行,对于两个线程必须以先后秩序执行的情况,我们可以用线程锁来处理。
线程锁的大致思想是:如果线程A和线程B会执行实例的两个函数a和b,如果A必须在B之前运行,那么可以在B进入b函数时让B进入wait set,直到A执行完a函数再把B从wait set中激活。这样就保证了B必定在A之后运行,无论在之前它们的时间先后顺序是怎样的。
线程锁的代码

如右,SwingComponentLock的实例就是一个线程锁,lock函数用于锁定线程,当完成状态isCompleted为false时进入的线程会进入SwingComponentLock的实例的wait set,已完成则不会;要激活SwingComponentLock的实例的wait set中等待的线程需要执行unlock函数。

public class SwingComponentLock {
  // 是否初始化完毕
  boolean isCompleted = false;

  /**
   * 锁定线程
   */
  public synchronized void lock() {
    while (!isCompleted) {
      try {
        wait();
      } catch (Exception e) {
        e.printStackTrace();
        logger.error(e.getMessage());
      }
    }
  }

  /**
   * 解锁线程
   *
   */
  public synchronized void unlock() {
    isCompleted = true;
    notifyAll();
  }
}
回复 使用道具 举报
线程锁主要通过关键字synchronized()来实现的
在你所开的线程里加上synchronized(锁)然后用同一把锁,就可以实现多线程中,限制多个线程对同一对象的操作时不会出现重复操作。
就像卖票窗口一样,多个窗口像多个线程,如果不加锁那么可能有两个窗口卖出了同一张票,线程锁就是为防止出现这样的情况而出现的,比如1号窗口卖001号票的时候,别的窗口要等到1号窗口操作完以后才能继续对票数进行操作。
再贴一个以前写的售票例子给你看看
  1. package cn.itcast.thread;

  2. /*
  3. * 需求:铁路售票,一共100张,通过四个窗口卖完.
  4. */
  5. public class Demo12_Tickets {

  6.         /**
  7.          * @param args
  8.          */
  9.         public static void main(String[] args) {
  10.                 new TicketsSeller().start();
  11.                 new TicketsSeller().start();
  12.                 new TicketsSeller().start();
  13.                 new TicketsSeller().start();
  14.                 /*TicketsSeller ts1 = new TicketsSeller();
  15.                 ts1.start();                        //多次启动一个线程是非法的
  16.                 ts1.start();
  17.                 ts1.start();
  18.                 ts1.start();*/
  19.         }

  20. }

  21. class TicketsSeller extends Thread {
  22.         private static int tickets = 100;
  23.         //private static Object obj = new Object();
  24.         public void run() {
  25.                 while (true) {
  26.                         synchronized (TicketsSeller.class) {
  27.                                 if (tickets <= 0)
  28.                                         break;
  29.                                 try {
  30.                                         Thread.sleep(10);// 1234
  31.                                 } catch (InterruptedException e) {

  32.                                         e.printStackTrace();
  33.                                 }
  34.                                 System.out.println(getName() + "------------这是第" + tickets--
  35.                                                 + "号票");// tickets = tickets - 1
  36.                         }
  37.                 }
  38.         }
  39. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
贺奕凯 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马