当前位置: 首页 > 知识库问答 >
问题:

同步方法vs Reenter antLock

景俊良
2023-03-14

假设我有一个服务器,它有多个线程,共享对一个数据实例的引用。快点,

编辑1:为了可读性而更新

public void main() {
 Data data = new Data();
 ReentrantLock rl = new ReentrantLock(true);
 ReadThread t1 = new ReadThread(data, rl);
 UploadThread t2 = new UploadThread(data, rl);
 t1.start(); t2.start();
}

class ReadThread extends Thread {
private Data data;
private ReentrantLock lock;

ReadThread(Data d, ReentrantLock l){ data = d; lock = l; }

     void run(){
        lock.lock();
        try{
        data.put(aString)
        } finally { lock.unlock(); }
     }
}

class UploadThread extends Thread {
private Data data;
private ReentrantLock lock;

UploadThread(Data d, ReentrantLock l){ data = d; lock = l; }

     void run(){
        lock.lock();
        try{
        data.put(aString)
        } finally { lock.unlock(); }
     }
}

是使用上面的锁更好,还是同步下面的put方法更好,

class Data {
 private LinkedList<String> data = new LinkedList<String>();
 synchronized void put(String x){ data.add(x); }
}

这很粗糙,

我主要关心的是并发。

使用同步方法,我假设同步将发生在类的“数据”实例/对象上,这是正确的吗?所以一个上传线程可以调用放置过程/方法,一个ReadThread可以并行地做同样的事情。然而,使用折衷锁示例,在任何时候只有一个线程能够执行放置调用?

如果在“Data”类中,我将LinkedList设置为静态,将put方法设置为同步和静态,会发生什么?哪种方法最好?如果我让东西静止,我会失去mut-ex吗?

共有1个答案

竺焕
2023-03-14

在Javasynchronized中,节是可重入的。这意味着单个线程可以根据需要多次进入synchronized部分,但新线程只能在没有其他线程的情况下进入。当前在这些节中的线程已获得锁,并且只有在离开所有同步节时才会返回锁。除了通过方法签名声明synchronized,还可以直接在对象上调用synchronized。例如这两种方法具有相同的效果:

synchronized public void foo() {

}

public void foo() {
    synchronized(this) {

    }
}

ReentrantLocksynchronized非常相似,因为一次只有一个线程可以获取锁。如果线程到达锁。lock()语句它将等待另一个线程解锁锁。如果线程已经拥有锁,它将继续。在一个同步代码块不够的更复杂的情况下,这可能很有用。

如果...我使put方法同步和静态会发生什么?

如果方法是静态同步的,则意味着锁定的是类本身,而不是类的实例。它独立于实例同步方法被锁定。

对于您的代码

这里最简单的方法是将Data对象转换为线程安全对象。如果您不能编辑这个类的代码,那么一个有效的策略是将对象包装在线程安全包装器中。

interface Foo {
    void bar();
} 
class UnsafeFoo implements Foo {
    @Override bar() { ... }
}
class ThreadSafeFoo implements Foo {
    Foo foo;
    ThreadSafeFoo(Foo foo) { this.foo = foo; } 
    @Override synchronized bar() { foo.bar(); }
}

Foo unsafe = new UnsafeFoo();
Foo safe = new ThreadSafeFoo(unsafe);
 类似资料:
  • 请看下面给我带来麻烦的方法: 然后是run方法:

  • 问题内容: 我正在查看包含同步方法的第三方库中的一些代码,在此方法中,有一个锁定在实例变量上的同步块。与此类似: 这有意义吗?如果是这样,在同步方法中使用同步语句有什么好处? 鉴于同步方法锁定了整个对象,对我来说似乎是多余的。在使用非私有的实例变量时,这种方法是否有意义? 问题答案: 在您的示例中,该方法 同时 锁定了和的实例。其他方法可能仅锁定对象的实例 或 对象。 因此,是的,这完全取决于他们

  • 为什么下面的代码不能保证多个线程之间total_home数字的唯一性,即使逻辑处于同步块中。 } } } 这是一个程序示例。试着运行5-10次,你会发现total_home的值并不是每次都是唯一的。

  • 我正试图从同步方法运行异步方法。但是我不能等待异步方法,因为我在同步方法中。我一定不理解TPL,因为这是我第一次使用它。 每个方法都需要前一个方法来完成,因为第一个方法的数据用于第二个方法。 Await运算符只能在异步方法中使用。考虑用'async'修饰符标记此方法,并将其返回类型更改为'task' 但是,如果我使用async修饰符,这将是一个异步操作。因此,如果我对的调用没有使用await运算符

  • 同步调用异步方法最安全的方法是什么?

  • 问题内容: 如何跨JVM同步方法? 我的示例是一个Web应用程序,该应用程序限制一个用户名不能多次登录(换句话说,第一个用户可以登录,但是如果另一个用户使用相同的用户名登录,他将被拒绝)。 该Web应用程序部署在多个服务器上,因此有多个JVM,并且用户可以尝试使用不同的服务器进行登录,具体取决于负载平衡器。 这是该方法的外观 由于采用了同步方法,因此它可以在1个应用服务器上正常工作,但是可以跨多个

  • 我正在编写的代码需要在几个静态方法之间进行一些同步。我的目标是阻止执行这些方法中的任何一个,如果其中一个执行。例如: 现在让我们假设下面的代码是从代码中的某个地方执行的: 我的问题是: > 它实际上是同步的吗?methodA和methodB不会同时运行吗? 如果是,methodA调用methodB会不会造成死锁?

  • 我有点困惑。请看看下面的代码。 我确信调用此序列是可能的。 虽然我仍然有一个小小的困惑,但我们可以很容易地看到也调用方法,这是一个静态方法。方法 是调用非同步静态方法的静态同步方法。当 thread-2 获得类级锁时,为什么从 Thread-1 调用 没有被阻止? 我只是在逻辑上感到困惑,如果一个线程获得类级锁定,则该类其他非同步静态方法保持打开状态,以便从其他方法(实例方法)调用。为什么?