`
youngerbaby
  • 浏览: 115061 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

转载:JavaSE的线程synchronized关键字的用法

    博客分类:
  • Java
阅读更多

 

原文:http://blog.tom.com/blog/read.php?bloggerid=780430...

synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法
:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
notify()及notifyAll()是Object的方法,与Object的wait()方法配合使用,而且这三个方法必须在同步块中调用.
如下:
在线程1中执行如下代码
...
synchronized(obj1)      //1.进入同步块
{
    try {
    ...
    obj1.wait();        //2.进入暂停状态
    }catch (InterruptedException exp) {}
}
1.当前同步对象(monitor)为obj1,obj1是任一实例,若是同步方法,则同步对象是this.进入同步块后,obj1为锁定状态,锁定状态对obj1本身无任何影响,而其它线程执行到同一代码时,因不能获得锁,处于Block状态,一旦解锁,被block的线程自动继续执行.
2.调用obj1.wait()有两个作用,一是使线程进入等待状态,二是解锁obj1,这时被block的线程将获得锁.线程1要退出等待必须要由其它线程显式的调用obj1.notify()或notifyAll()方法.

...
synchronized(obj1)
{
    ...
    obj1.notify();    //3. 向wait的线程发通知信息
    ...
}
...
若其它线程执行到此时,线程1处于wait状态,则wait状态解除,解除后,若线程1若得到锁就能继续执行,若有多个线程处于obj1的wait状态,notify将随机选一个线程激活,而notifyAll是同时解除所有的wait状态.
notifyAll()让等待某个对象K的所有线程离开阻塞状态,
notify()随机地选取等待某个对象K的线程,让它离开阻塞状态。
notify(),notifyAll()非常有用,在一个synchronized(lockObj)块中当调用lockObj.wait()时,线程就已经将锁放开来了,这时当另外一个线程调用lockObj.notify()时,等待的线程就会继续执行下去了。这是一种非常高效的线程同步机制。如果没有他,用sleep()来同步的话就太浪费时间了。
一个简单的例子:
thread1 receive data
thread2 pase received data
lockObj是buf
当buf中没有数据时,thread2中调用buf.wait释放锁,让thread1有机会执行。
当thread1收到数据时,调用buf.notify()通知thread1去处理收到的数据。
如果在同步块入口点阻塞,不须其它线程调用notify(),调了也没效果,同步块能自动获得锁
如果是wait造成了阻塞,须用notfiy()激活,这两个方法是配合使用
notify、notifyAll、wait :
主要是为了解决持有监视器钥匙的线程暂停等待另一线程完成时可能发生死锁的问题。wait()方法使调用线程等待,直到发生超时或另一线程调用同一对象的notify()或notifyAll()方法。wait() 方法的用法如下:wait()或wait(long timeoutPeriodInMilliseconds)前者等待被通知,后者等待超时或通知。线程调用wait()方法时,释放所持有的钥匙让另一等待线程进入监视区。notify()方法只唤醒一个等待线程,而notifyAll()唤醒所有等待该监视器的线程。注意,这些方法只能在监视区内调用。否则会输出一种RuntimeException类型的IllegaMonitorStateException异常状态。
够详细清楚的吧。
      总之wait()让线程等待,notify()和notifyall()激活某个等待线程,其实就是撤销该线程的中断状态,从而使他们有机会再次运行
       有时会遇到如下问题,程序的一部分在写数据,另一部分读数据,但有时会出现读部分超前写部分,
这就是典型的产生者/消耗者问题.
   .wait:是一个线程睡眠,直到在相同的对象上调用notify或notifyAll
   .notify:启动第一个在相同对象调用wait的线程
   .notifyAll:启动在相同的对象调用wait的所有线程

Trackback: http://tb.blog.csdn.net/TrackBack.aspx PostId=1373947

分享到:
评论

相关推荐

    JavaSE多线程

    这些方法必须在`synchronized`代码块或方法中使用,`wait()`会使当前线程等待并释放锁,`notify()`随机唤醒一个等待的线程,而`notifyAll()`会唤醒所有等待的线程。 在实际应用中,多线程编程常常涉及到银行系统的...

    JavaSE:JavaSE学习笔记

    - **同步机制**:理解synchronized关键字的作用,以及wait()、notify()和notifyAll()的用法。 - **线程池**:了解ExecutorService和ThreadPoolExecutor,有效管理并发线程。 7. **反射机制** - **Class类**:...

    JavaSE 多线程必背程序清单

    解决这类问题通常需要使用同步机制,如 `synchronized` 关键字,或者使用 `ReentrantLock` 等高级锁来确保线程安全。 总结来说,Java中的多线程是通过继承 `Thread` 类或实现 `Runnable` 接口来创建的。理解多线程...

    JavaSE:javaSE的所有基础知识

    - **同步机制**:synchronized关键字,wait()、notify()和notifyAll()方法,以及Lock接口。 - **线程池**:ExecutorService、ThreadPoolExecutor和ScheduledThreadPoolExecutor的使用。 7. **网络编程**: - **...

    JavaEE学习[JavaSE-06多线程.rar]

    Java提供了丰富的线程API,包括线程的启动(start())、同步(synchronized关键字,wait(),notify(),notifyAll())、线程状态管理(isAlive(), join())以及线程池(ExecutorService,ThreadPoolExecutor,Future...

    JavaSENote:JavaSE学习笔记

    - **线程同步**:synchronized关键字,wait()、notify()和notifyAll()方法。 - **线程池**:ExecutorService和ThreadPoolExecutor的使用。 12. **反射机制** - **Class类**:获取类的信息,动态创建对象,调用...

    javase-:javase基础代码仓库

    - 线程同步:synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和相关的工具类,用于防止数据竞争。 7. **网络编程**: - Java的Socket和ServerSocket类提供了TCP/IP网络通信的基础。 - URL...

    java源码知乎-JavaSE:JavaSE知乎专栏源代码,知乎专栏:https://zhuanlan.zhihu.com/javase

    - **线程同步**:了解synchronized关键字、wait()、notify()和notifyAll()方法,以及死锁的概念。 7. **网络编程**: - **Socket编程**:学习如何使用Socket和ServerSocket进行TCP通信。 - **HTTP协议与URL连接*...

    javaSE多线程的案例源代码

    Java提供了多种同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和ReentrantLock类。源代码中可能包含了使用这些同步工具的示例,例如银行账户转账操作,确保在任何时候只有一个...

    JavaSE多线程三PPT教案学习.pptx

    这两个方法都使用`synchronized`关键字进行同步,确保同一时间只有一个线程可以执行。当条件满足(如库存满或空)时,店员会调用`wait()`方法让线程等待,并在适当的时候调用`notify()`或`notifyAll()`唤醒等待的...

    马士兵多线程笔记.zip

    4. **线程同步**:为了避免多个线程之间的数据竞争问题,Java提供了多种同步机制,如synchronized关键字、wait()和notify()方法、Lock接口(如ReentrantLock)以及Semaphore等。正确使用同步机制能保证线程安全,...

    javaSE常用相关技术

    - **同步**:为了保证线程安全,Java提供了多种同步机制,如synchronized关键字、ReentrantLock等。 #### 四、集合 集合是Java中用于存储和操作一组对象的数据结构。 - **常见集合类**: - List:有序的、可...

    JavaSE6_API

    4. **多线程**:`java.lang.Thread`类和`java.util.concurrent`包提供了多线程编程的支持,包括线程的创建、同步、并发控制,如`synchronized`关键字、`Thread.join()`、`ExecutorService`、`Future`等。 5. **网络...

    JAVASE综合测试题及答案

    解释:线程可以通过使用 synchronized 关键字来获得对象的互斥锁定,以实现线程安全。 2. 在面向对象编程里,经常使用 is-a 来说明对象之间的继承关系,下列对象中 不具备继承关系的是? 答案:D 中国与北京 解释...

    javaSE小项目|java项目,javaSE练手小项目

    项目中可能会涉及到线程的创建、同步控制(如synchronized关键字、wait()、notify()方法)以及线程池的使用。 6. **集合框架**:Java集合框架提供了多种容器,如ArrayList、LinkedList、HashSet、HashMap等,用于...

    JavaSE总结文档.rar

    - **多线程**:线程的创建与管理,synchronized关键字,线程同步与通信(如wait()、notify()、notifyAll())。 3. **JavaSE基础知识总结之三**: - **反射机制**:理解Class类,动态获取类信息,创建对象,调用...

    javase总结

    3. **线程同步**:掌握synchronized关键字,了解死锁、活锁、饥饿等问题。 4. **线程通信**:学习wait、notify和notifyAll方法,以及CountDownLatch、CyclicBarrier等高级工具。 九、反射 1. **Class类**:通过...

    王道JavaSE阶段测试

    6. **多线程**:线程的创建方式(继承Thread类和实现Runnable接口),线程同步(synchronized关键字,wait(),notify(),notifyAll()方法,Lock接口),线程池。 7. **网络编程**:Socket编程,ServerSocket,TCP与...

    JavaSE基础入门视频教程33天之(27) part1

    - "线程等待与唤醒案例介绍"可能涉及到线程间的协作,如`wait()`、`notify()`和`notifyAll()`方法,这些方法用于线程的等待和唤醒操作,通常与`synchronized`一起使用。 通过这个视频教程,初学者能够掌握Java多...

Global site tag (gtag.js) - Google Analytics