黑马程序员技术交流社区

标题: 对同一对象加锁,如何实现同步? [打印本页]

作者: 张凯    时间: 2012-7-20 17:39
标题: 对同一对象加锁,如何实现同步?


  1. package ThreadTest;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;

  4. public class TicketTest {

  5. public static void main(String[] args) {
  6. TicketsThread tt = new TicketsThread();
  7. Thread station1 = new Thread(tt, "售票点1");
  8. Thread station2 = new Thread(tt, "售票点2");
  9. Thread station3 = new Thread(tt, "售票点3");
  10. station1.start();
  11. station2.start();
  12. station3.start();
  13. }
  14. }

  15. class TicketsThread implements Runnable {
  16. int tickets = 0;

  17. public void run() {

  18. Lock lock = new ReentrantLock();//注意在run方法中
  19. while (true) {
  20. lock.lock();
  21. if (tickets < 100) {
  22. tickets++;
  23. System.out.println(Thread.currentThread().getName() + "售出第"
  24. + tickets + "张票");
  25. }
  26. try {
  27. Thread.sleep(50);
  28. } catch (InterruptedException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. lock.unlock();
  33. }
  34. }

  35. }
复制代码
多个线程分别创建了锁实例后对同一对象加锁,不能实现同步的原因。具体解释一下。谢了
现在我有个疑问是:“多个线程分别创建了锁实例后对同一对象加锁”,与“jvm为每个对象都关联了唯一的一把锁”。二者好像矛盾?
作者: 王宝康    时间: 2012-7-20 18:02
本帖最后由 王宝康 于 2012-7-20 18:09 编辑
  1. package thread;

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

  4. public class TicketTest {

  5.         public static void main(String[] args) {
  6.                 TicketsThread tt = new TicketsThread();
  7.                 Thread station1 = new Thread(tt, "售票点1");
  8.                 Thread station2 = new Thread(tt, "售票点2");
  9.                 Thread station3 = new Thread(tt, "售票点3");
  10.                 station1.start();
  11.                 station2.start();
  12.                 station3.start();
  13.         }
  14. }

  15. class TicketsThread implements Runnable {
  16.         int tickets = 0;
  17.         Lock lock = new ReentrantLock();//这儿,你把锁定义到了run()方法时,所有的线程都会运行run()方法,然后new了它们自己的lock对象,各自持有自己的锁
  18.                                                            //所以没能实现同步
  19.       public void run() {

  20.                 // 注意在run方法中
  21.                 while (true) {
  22.                         lock.lock();
  23.                         if (tickets < 100) {
  24.                                 tickets++;
  25.                                 System.out.println(Thread.currentThread().getName() + "售出第"
  26.                                                 + tickets + "张票");
  27.                         }
  28.                         
  29.                                 try {
  30.                                         Thread.sleep(50);
  31.                                 } catch (InterruptedException e) {
  32.                                         // TODO Auto-generated catch block
  33.                                         e.printStackTrace();
  34.                                 }finally{
  35.                                         lock.unlock();//这儿,你的代码中,没有把lock.unlock()用finally包起来,这儿是一定要用finally包起来的,
  36.                                                             //保证它必须运行来释放锁,以使别的线程有机会获得锁
  37.                                 }                                       
  38.                 }
  39.         }

  40. }
复制代码

作者: themoon    时间: 2012-7-20 18:43
线程的同步是为了阻止在两个及两个以上的线程同时运行时,在对同一资源的访问时发生的冲突。对于你的这段程序来说,你声明的三个线程都应该遵循待前一个线程完全释放了资源之后,下一个线程才可以访问的。
具体应该这样加锁:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TicketTest {
       
        public static void main(String[] args) {
                TicketsThread tt = new TicketsThread();
                Thread station1 = new Thread(tt, "售票点1");
                Thread station2 = new Thread(tt, "售票点2");
                Thread station3 = new Thread(tt, "售票点3");
                station1.start();
                station2.start();
                station3.start();
        }
}

class TicketsThread implements Runnable {
        int tickets = 0;

        public void run() {

                Lock lock = new ReentrantLock();// 注意在run方法中

                while (true) {
                        lock.lock();
                        if (tickets < 100) {
                                tickets++;
                                System.out.println(Thread.currentThread().getName() + "售出第" + tickets + "张票");
                        }
                        try {
                                Thread.sleep(50);
                                lock.unlock();
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                }
        }

}
而你说的另一个问题:“多个线程分别创建了锁实例后对同一对象加锁”,与“jvm为每个对象都关联了唯一的一把锁”。二者好像矛盾?
以你的代码来看,这句话是矛盾的,因为你每个线程都是共享同一实例。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2