首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >线程获取电平

线程获取电平
EN

Stack Overflow用户
提问于 2012-08-21 22:35:43
回答 4查看 372关注 0票数 1

我不清楚

Java在进入实例同步java方法时获取对象级锁,在进入静态同步java方法时获取类级锁

当它说对象级锁和类级锁时,意味着什么?

例如,

代码语言:javascript
运行
复制
 public class Counter{
      private static int count = 0;
      private int count2 = 0;

      public static synchronized int getCount(){
           return count;
      }
      public synchronized setCount(int count2){
           this.count2 = count2;
      }
 } 

getCount()在这里将锁定Counter.class对象,而setCount()将锁定当前对象(此)。这个指的是什么?这是否意味着当getCount()被调用时,另一个线程不能访问setCount(),因为整个类都被锁定了?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-08-22 14:36:27

当它说对象级锁和类级锁时,意味着什么?

当您锁定一个static方法时,您将锁定Class对象本身,并且每个ClassLoader都有其中一个。在你的例子中,

代码语言:javascript
运行
复制
public static synchronized int getCount(){

这是对Counter.class对象的锁定,与以下相同:

代码语言:javascript
运行
复制
public static int getCount() {
    synchronized (Counter.class) {
    }

如果您正在锁定一个不是static的方法,那么您将锁定拥有该方法的对象的实例。在你的例子中:

代码语言:javascript
运行
复制
public synchronized void setCount(int count){

这与锁定特定的Counter实例相同,相当于:

代码语言:javascript
运行
复制
public void setCount(int count){
    synchronized (this) {
       ...

因此,如果有两个Counter对象,counter1counter2,而一个线程同时调用counter1.getCount(),另一个线程同时调用counter2.getCount(),那么它们都会锁定同一个Class对象,其中一个会阻塞另一个。

但是,如果这两个线程正在调用counter1.setCount(...)counter2.setCount(),那么它们将锁定不同的对象-- counter1counter2。他们不会互相阻拦。

如前所述,在setter和getter上存在不对称的形式是非常糟糕的,而且不寻常的是,要么是static

这是否意味着当getCount()被调用时,另一个线程不能访问setCount(),因为整个类都被锁定了?

不是的。如果调用getCount(),则Counter.class被锁定,而当setCount(...)被称为counter1counter2时,则被锁定。只有当同一个对象被另一个线程锁定时,锁才会阻塞线程。仅仅因为Counter.class上有一个锁,并不意味着存在某种uber类锁。阻止另一个线程的唯一时间是如果它在Counter.class上太锁。

我会花点时间读一下Sun的作品

票数 1
EN

Stack Overflow用户

发布于 2012-08-21 22:37:51

在Java中,类的每个类和每个实例都具有它们的内部锁。这些是在进入和退出synchronized方法时获得和释放的锁。

与往常一样,this引用调用setCount()的实例,因为每个实例都有自己的内部锁,所以只要对类的另一个实例调用setCount(),对setCount()的第二次调用就不会被阻塞,但是对正在进行另一个setCount()调用的实例调用setCount()的尝试将被阻止。

类锁和实例锁是不同的,因此getCount()setCount()永远不会互相干扰。

票数 1
EN

Stack Overflow用户

发布于 2012-08-21 22:40:58

static成员与类关联,而不是与特定实例关联。因此,static成员上的同步在整个类上有效地同步,因为静态是类成员。

实例成员与类的实例相关联(例如,复杂的this锁),因此如果您在成员字段(非静态)或this上同步,那么您就有一个与实例对象相关联的锁。

在您的示例中,getCount在类的intrinsik锁上同步。实际上你正在做的是:

代码语言:javascript
运行
复制
public setCount(int count){
    synchronized(this){
        this.count = count;
    }  
}

如果您这样做了,那么您将在类级别进行同步:

代码语言:javascript
运行
复制
static Object count = new Object();  
synchronized(count){  

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12064041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档