Java 为什么我们需要为同步语句指定锁?
既然一个类的每个实例只有一个锁,那么为什么Java不允许我们这样做:Java 为什么我们需要为同步语句指定锁?,java,concurrency,synchronized,Java,Concurrency,Synchronized,既然一个类的每个实例只有一个锁,那么为什么Java不允许我们这样做: void method() { synchronized { // do something } // do other things } void method() { synchronized { // do something } // do other things } 与此相反: void method() { synch
void method() {
synchronized {
// do something
}
// do other things
}
void method() {
synchronized {
// do something
}
// do other things
}
与此相反:
void method() {
synchronized (lock) {
// do something
}
// do other things
}
指定锁的目的是什么?如果我选择一个对象作为锁而不是另一个对象,会有区别吗?或者我可以随便选一个对象吗
编辑:
事实证明,我对同步方法的理解在基本层面上是错误的
我认为不同的同步方法或块是完全独立的,不考虑锁。相反,具有相同锁的所有同步方法或块只能由一个线程访问,即使这些同步方法/块来自不同的类(文档应该更强调这一点:所有同步的方法/块,无论位置如何,重要的是锁)。synchronized中的(锁)
,锁可以是对象级锁,也可以是类级锁
- 示例1类级别锁:
private static Object lock=new Object();
synchronized (lock){
//do Something
}
private Object lock=new Object();
synchronized (lock){
//do Something
}
- 示例2对象级别锁定:
private static Object lock=new Object();
synchronized (lock){
//do Something
}
private Object lock=new Object();
synchronized (lock){
//do Something
}
在同步(锁)
中,锁可以是对象级锁,也可以是类级锁
- 示例1类级别锁:
private static Object lock=new Object();
synchronized (lock){
//do Something
}
private Object lock=new Object();
synchronized (lock){
//do Something
}
- 示例2对象级别锁定:
private static Object lock=new Object();
synchronized (lock){
//do Something
}
private Object lock=new Object();
synchronized (lock){
//do Something
}
这样你就可以锁定与完全不同的东西
还记得Vector
是如何“线程安全”的吗?其实并不是那么简单;每次调用都是,但这样的代码并不是因为它可以在获取向量大小和获取元素之间进行更新:
for (int i = 0; i < vector.size(); ++i) System.out.println(vector.get(i));
这可能是一种非线程安全、不同步或使用可重入锁定
的方法;锁定向量与锁定此
是分开的,因此您可以锁定与此
完全不同的内容
还记得Vector
是如何“线程安全”的吗?其实并不是那么简单;每次调用都是,但这样的代码并不是因为它可以在获取向量大小和获取元素之间进行更新:
for (int i = 0; i < vector.size(); ++i) System.out.println(vector.get(i));
这可能是在非线程安全、不同步或使用可重入锁定
的方法中;锁定向量与锁定此
是分开的
既然一个类的每个实例只有一个锁,那么为什么Java不允许我们这样做:
void method() {
synchronized {
// do something
}
// do other things
}
void method() {
synchronized {
// do something
}
// do other things
}
虽然每个实例都提供了一个内部锁,
这不一定是要使用的“明显”锁
您可能是对的,他们可以提供synchronized{…}
作为synchronized(this){…}
的缩写。
我不知道他们为什么没有,但我从未错过。
但是并发编程很棘手,
因此,将lock对象作为一个显式的必需参数可能会让读者更清楚,正如@ajb在一篇评论中指出的那样,这是一件好事。
无论如何,我不认为语法是你的主要问题,所以让我们继续
指定锁的目的是什么
嗯,锁可能是同步机制中最重要的一件事。同步的关键点是,只有一个线程可以持有相同的锁。持有不同锁的两个线程不同步。因此,知道什么是保护同步的锁是至关重要的
如果我选择一个对象作为锁而不是另一个对象,会有区别吗
我希望上一节明确指出,是的,您必须仔细选择对象。它必须是所有相关线程都可以看到的对象,
它必须不为null,并且必须是在同步期间不会被重新分配的内容
或者我可以随便选一个对象吗
当然不是。见上一节
为了理解Java中的并发性,我推荐API作者之一的书,或者是关于这个主题的书
既然一个类的每个实例只有一个锁,那么为什么Java不允许我们这样做:
void method() {
synchronized {
// do something
}
// do other things
}
void method() {
synchronized {
// do something
}
// do other things
}
虽然每个实例都提供了一个内部锁,
这不一定是要使用的“明显”锁
您可能是对的,他们可以提供synchronized{…}
作为synchronized(this){…}
的缩写。
我不知道他们为什么没有,但我从未错过。
但是并发编程很棘手,
因此,将lock对象作为一个显式的必需参数可能会让读者更清楚,正如@ajb在一篇评论中指出的那样,这是一件好事。
无论如何,我不认为语法是你的主要问题,所以让我们继续
指定锁的目的是什么
嗯,锁可能是同步机制中最重要的一件事。同步的关键点是,只有一个线程可以持有相同的锁。持有不同锁的两个线程不同步。因此,知道什么是保护同步的锁是至关重要的
如果我选择一个对象作为锁而不是另一个对象,会有区别吗
我希望上一节明确指出,是的,您必须仔细选择对象。它必须是所有相关线程都可以看到的对象,
它必须不为null,并且必须是在同步期间不会被重新分配的内容
或者我可以随便选一个对象吗
当然不是。见上一节
为了理解Java中的并发性,我推荐API作者之一的书,或者关于这个主题的书。如果您有多个对象,b1/b2需要更新并发性
class A {
private B b1, b2;
}
如果你只有一把锁,就说是A类锁
synchronized (this) { ... }
然后假设有两个线程同时更新b1和b2,它们将逐个播放,因为已同步(此)
但如果b1和b2有两个锁
private Object lock1 = new Object, lock2 = new Object;
我提到的两个线程将同时运行,因为