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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© jialihong 中级黑马   /  2013-7-24 13:58  /  908 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨兴庭 于 2013-7-25 22:39 编辑

线程同步的方法有哪些?

评分

参与人数 1黑马币 +3 收起 理由
杨兴庭 + 3

查看全部评分

4 个回复

倒序浏览
1  wait方法:
        该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态(一旦获得锁就恢复执行)。
        调用wait方法需要注意几点:
        第一点:wait被调用的时候必须在拥有锁(即synchronized修饰的)的代码块中。
        第二点:恢复执行后,从wait的下一条语句开始执行,因而wait方法总是应当在while循环中调用,以免出现恢复执行后继续执行的条件不满足却继续执行的情况。
        第三点:若wait方法参数中带时间,则除了notify和notifyAll被调用能激活处于wait状态(等待状态)的线程进入锁竞争外,在其他线程中interrupt它或者参数时间到了之后,该线程也将被激活到竞争状态。
        第四点:wait方法被调用的线程必须获得之前执行到wait时释放掉的锁重新获得才能够恢复执行。

2  notify方法和notifyAll方法:
        notify方法通知调用了wait方法,但是尚未激活的一个线程进入线程调度队列(即进入锁竞争),注意不是立即执行。并且具体是哪一个线程不能保证。另外一点就是被唤醒的这个线程一定是在等待wait所释放的锁。
        notifyAll方法则唤醒所有调用了wait方法,尚未激活的进程进入竞争队列。

3 synchronized关键字:
        第一点:synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象的锁。
        第二点:synchronized用来标识一个静态方法时,表示一个线程要执行该方法,必须获得该方法所在的类的类锁。
        第三点:synchronized修饰一个代码块。类似这样:synchronized(obj) { //code.... }。表示一个线程要执行该代码块,必须获得obj的锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。利用零长度的byte数组对象做obj非常经济。

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 月亮人生 于 2013-7-24 14:22 编辑

wait():让线程等待。将线程存储到一个线程池中。
notify():唤醒被等待的线程。通常都唤醒线程池中的第一个。让被唤醒的线程处于临时阻塞状态。
notifyAll(): 唤醒所有的等待线程。将线程池中的所有线程都唤醒,让它们从冻结状体转到临时阻塞状态
synchronized:用于修饰同步代码块和同步方法。
(在jdk1.5版本之后,出现了一些新的特性。在java.util.concurrent.locks包中提供了一个接口Lock,替代了synchronized。)

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报 1 0
当多条线程(执行单元)共同操作同一段代码时,为了安全,一般要对这段代码进行同步,因为CPU的切换千变外化。
线程同步的方法有两个,一个是同步函数,一个是同步代码块。
同步函数直接在要同步的函数加上synchronized关键字即可,同步函数的锁是:this,当前对象。
同步代码块synchronized(对象){需要被同步的代码;}锁可以是任意的对象,当静态时,一般用当前对象的字节码。

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 董凯 于 2013-7-24 21:20 编辑
  1.   Java线程:线程的同步
  2.    
  3.  public class Test {
  4.   public static void main(String[] args) {
  5.   User u = new User("张三", 100);
  6.   MyThread t1 = new MyThread("线程A", u, 20);
  7.   MyThread t2 = new MyThread("线程B", u, -60);
  8.   MyThread t3 = new MyThread("线程C", u, -80);
  9.   MyThread t4 = new MyThread("线程D", u, -30);
  10.   MyThread t5 = new MyThread("线程E", u, 32);
  11.   MyThread t6 = new MyThread("线程F", u, 21);
  12.   t1.start();
  13.   t2.start();
  14.   t3.start();
  15.   t4.start();
  16.   t5.start();
  17.   t6.start();
  18.   }
  19.   }
  20.   class MyThread extends Thread {
  21.   private User u;
  22.   private int y = 0;
  23.   MyThread(String name, User u, int y) {
  24.   super(name);
  25.   this.u = u;
  26.   this.y = y;
  27.   }
  28.  public void run() {
  29.   u.oper(y);
  30.   }
  31.   }
  32. class User {
  33.   private String code;
  34.   private int cash;
  35.   User(String code, int cash) {
  36.   this.code = code;
  37.   this.cash = cash;
  38.   }
  39.   public String getCode() {
  40.   return code;
  41.   }
  42.   public void setCode(String code) {
  43.   this.code = code;
  44.   }
  45.   /**
  46.  * 业务方法
  47.   * @param x 添加x万元
  48.   */
  49.   public synchronized void oper(int x) {
  50.   try {
  51.   Thread.sleep(10L);
  52.   this.cash += x;
  53.   System.out.println(Thread.currentThread().getName() + "运行结束,增加" + x + "","当前用户账户余额为:" + cash);
  54.   Thread.sleep(10L);
  55.   } catch (InterruptedException e) {
  56.   e.printStackTrace();
  57.   }
  58.   }
  59.   @Override
  60.   public String toString() {
  61.   return "User{" + "code=’" + code + ’\’’ + ", cash=" + cash +’}’;
  62.   }
  63.   }
  64. 输出结果:线程A运行结束,增加“20”,当前用户账户余额为:120。
  65.   线程F运行结束,增加“21”,当前用户账户余额为:141。
  66.   线程E运行结束,增加“32”,当前用户账户余额为:173。
  67. 线程C运行结束,增加“-80”,当前用户账户余额为:93。
  68.   线程B运行结束,增加“-60”,当前用户账户余额为:33。
  69.   线程D运行结束,增加“-30”,当前用户账户余额为:3。
  70.   Process finished with exit code 0反面教材,不同步的情况,也就是去掉oper(int x)方法的synchronized修饰符,然后运行程序,结果如下:线程A运行结束,增加“20”,当前用户账户余额为:61。
  71.   线程D运行结束,增加“-30”,当前用户账户余额为:63。
  72.   线程B运行结束,增加“-60”,当前用户账户余额为:3。
  73.   线程F运行结束,增加“21”,当前用户账户余额为:61。
  74.   线程E运行结束,增加“32”,当前用户账户余额为:93。
  75.   线程C运行结束,增加“-80”,当前用户账户余额为:61。
  76.   Process finished with exit code 0很显然,上面的结果是错误的,导致错误的原因是多个线程并发访问了竞争资源u,并对u的属性做了改动。可见同步的重要性。注意:通过前文可知,线程退出同步方法时将释放掉方法所属对象的锁,但还应该注意的是,同步方法中还可以使用特定的方法对线程进行调度。这些方法来自于java.lang.Object类,void notify()。
  77.   唤醒在此对象监视器上等待的单个线程。
  78.   void notifyAll()
  79.   唤醒在此对象监视器上等待的所有线程。
  80.   void wait()
  81.   导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
  82.   void wait(long timeout)
  83.   导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
  84.   void wait(long timeout, int nanos)
  85.   导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
复制代码

评分

参与人数 1技术分 +2 收起 理由
杨兴庭 + 2 很给力!

查看全部评分

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