黑马程序员技术交流社区
标题:
关于多线程的同步的问题
[打印本页]
作者:
华行天下
时间:
2013-9-28 12:32
标题:
关于多线程的同步的问题
本帖最后由 华行天下 于 2013-9-28 13:47 编辑
关于多线程的同步synchronized和lock有点混不太懂,不知道这两个什么分别什么时候用;希望得到大家的帮助;
作者:
hanfei2511
时间:
2013-9-28 12:59
关于多线程的同步synchronized和lock有点混不太懂,不知道这两个什么分别什么时候用;希望得到大家的帮助;
关于这个问题,我想最普遍的解释(常常作为答案的)就是下面所说的:
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。
虽然不错,但是在我总结这方面的时候,我搜集了别人对这个问题更好更全的解释:
synchronized块的确不错,但是他有一些功能性的限制:
1. 它无法中断一个正在等候获得锁的线程,也无法通过投票得到锁,如果不想等下去,也就没法得到锁。
2.synchronized 块对于锁的获得和释放是在相同的堆栈帧中进行的。多数情况下,这没问题(而且与异常处理交互得很好),但是,确实存在一些更适合使用非块结构锁定的情况。
java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。
JDK 官方文档中提到:
ReentrantLock是“一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。 ”
简单来说,ReentrantLock有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放。这模仿了 synchronized 的语义;如果线程进入由线程已经拥有的监控器保护的 synchronized 块,就允许线程继续进行,当线程退出第二个(或者后续) synchronized 块的时候,不释放锁,只有线程退出它进入的监控器保护的第一个 synchronized 块时,才释放锁。
ReentrantLock 类(重入锁)实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)
当然这不是我总结的,但我感觉很全面,当然原文中还有例子,你可以通过他的例子来理解上面的内容。原文还包括解释到此步还会存在的问题及解决方法,您如果感兴趣可以点击下面的链接:
http://www.java3z.com/cwbwebhome/article/article8/895.html
希望对您有帮助。
作者:
a283398689
时间:
2013-9-28 13:39
下面是我给你写的代码 你自己读读 就明白
package num10;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
// java 读写锁
class M
{
private static Map<Integer, String> map = new HashMap<Integer, String>();
private static M m = new M(map);
public static M getInstance()
{
return m;
}
private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock r = lock.readLock();
private final Lock w = lock.writeLock();
public M(Map<Integer, String> map) {
this.map = map;
}
public String put(Integer key, String value) {
System.out.println("waiting put");
w.lock();
try {
System.out.println("processing put");
try {
Thread.sleep(5000l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map.put(key, value);
} finally {
System.out.println("put finish");
w.unlock();
}
}
public synchronized String put1(Integer key, String value) {
System.out.println("waiting put1");
try {
System.out.println("processing put1");
try {
Thread.sleep(5000l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map.put(key, value);
} finally {
System.out.println("put1 finish");
}
}
public String get(Object key) {
System.out.println("waiting get");
r.lock();
try {
System.out.println("processing get");
try {
Thread.sleep(5000l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map.get(key);
} finally {
System.out.println("get finish");
r.unlock();
}
}
public synchronized String get1(Object key) {
System.out.println("waiting get1");
try {
System.out.println("processing get1");
try {
Thread.sleep(5000l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map.get(key);
} finally {
System.out.println("get1 finish");
}
}
}
public class ReadWriteLock implements Runnable
{
private int i;
private boolean get;
ReadWriteLock(int i, boolean get)
{
this.i = i;
this.get = get;
}
public void run()
{
M m = M.getInstance();
if (get)
{
m.get1(new Integer(1));
}
else
{
m.put1(new Integer(1), "1");
}
}
public static void main(String[] args)
{
boolean getfirst = false;
ReadWriteLock c = new ReadWriteLock(0, !getfirst);
Thread t = new Thread(c);
t.start();
ReadWriteLock c2 = new ReadWriteLock(1, getfirst);
Thread t2 = new Thread(c2);
t2.start();
}
}
运行结果如下:
waiting get1
processing get1
get1 finish
waiting put1
processing put1
put1 finish
可以看出synchronized 关键字相当于 lock(M.class), 是将整个对象锁住,为提高效率,可以使用读写锁
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2