本文目录一览:
- 1、java synchronized对静态方法加锁
- 2、java中多线程使用lock锁 其中一个使用unlock方法为什么锁就失效了
- 3、java中synchronized函数锁,锁的是什么?
- 4、java 对象锁和方法锁有什么区别
java synchronized对静态方法加锁
2所有的非静态同步方法用的都是同一把锁——实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。
而所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!
java中多线程使用lock锁 其中一个使用unlock方法为什么锁就失效了
Java中Lock,tryLock,lockInterruptibly的区别如下:
一、 lock()方法
使用lock()获取锁,若获取成功,标记下是该线程获取到了锁(用于锁重入),然后返回。若获取失败,这时跑一个for循环,循环中先将线程阻塞放入等待队列,当被调用signal()时线程被唤醒,这时进行锁竞争(因为默认使用的是非公平锁),如果此时用CAS获取到了锁那么就返回,如果没获取到那么再次放入等待队列,等待唤醒,如此循环。其间就算外部调用了interrupt(),循环也会继续走下去。一直到当前线程获取到了这个锁,此时才处理interrupt标志,若有,则执行 Thread.currentThread().interrupt(),结果如何取决于外层的处理。lock()最终执行的方法如下:
[java] view plain copy
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head tryAcquire(arg)) { //如果竞争得到了锁
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted; //获取成功返回interrupted标志
}
// 只修改标志位,不做其他处理
if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
其中parkAndCheckInterrupt()调用了LockSupport.park(),该方法使用Unsafe类将进程阻塞并放入等待队列,等待唤醒,和await()有点类似。
可以看到循环中检测到了interrupt标记,但是仅做 interrupted = true 操作,直到获取到了锁,才return interrupted,然后处理如下
[java] view plain copy
public final void acquire(int arg) {
if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt(); // 执行Thread.currentThread().interrupt()
}
二、 lockInterruptibly()方法
和lock()相比,lockInterruptibly()只有略微的修改,for循环过程中,如果检测到interrupt标志为true,则立刻抛出InterruptedException异常,这时程序变通过异常直接返回到最外层了,又外层继续处理,因此使用lockInterruptibly()时必须捕捉异常。lockInterruptibly()最终执行的方法如下:
[java] view plain copy
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return; //获取成功返回
}
if (shouldParkAfterFailedAcquire(p, node)
parkAndCheckInterrupt())
throw new InterruptedException(); //直接抛出异常
}
} finally {
if (failed)
cancelAcquire(node);
}
}
三、 tryLock()方法
使用tryLock()尝试获取锁,若获取成功,标记下是该线程获取到了锁,然后返回true;若获取失败,此时直接返回false,告诉外层没有获取到锁,之后的操作取决于外层,代码如下:
[java] view plain copy
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
java中synchronized函数锁,锁的是什么?
修饰方法就代表锁的是此方法体,如 public synchronized int cal(){...} 表示每次访问此方法都只能一个线程访问,其他的要等待访问完了才能进入此方法,这是竞争锁,synchronized(obj)锁的是obj,代表只有获取了此obj锁,才能继续访问,更高级的推荐使用Lock或ReentrainLock。
java 对象锁和方法锁有什么区别
对象锁类锁
对象锁
当一个对象中有synchronized
method或synchronized
block的时候调用此对象的同步方法或进入其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调用者占用,则需要等待此锁被释放
同步静态方法/静态变量互斥体
由于一个class不论被实例化多少次,其中的静态方法和静态变量在内存中都只由一份。所以,一旦一个静态的方法被申明为synchronized。此类所有的实例化对象在调用此方法,共用同一把锁,我们称之为类锁。一旦一个静态变量被作为synchronized
block的mutex。进入此同步区域时,都要先获得此静态变量的对象锁
类锁
由上述同步静态方法引申出一个概念,那就是类锁。其实系统中并不存在什么类锁。当一个同步静态方法被调用时,系统获取的其实就是代表该类的类对象的对象锁
在程序中获取类锁
可以尝试用以下方式获取类锁
synchronized
(xxx.class)
{...}
synchronized
(Class.forName("xxx"))
{...}
同时获取2类锁
同时获取类锁和对象锁是允许的,并不会产生任何问题,但使用类锁时一定要注意,一旦产生类锁的嵌套获取的话,就会产生死锁,因为每个class在内存中都只能生成一个Class实例对象。