在我的示例中,同步和锁定有什么区别?

我写了一个简单的代码来使用 Locksynchronized 来模拟并发.

I wrote a simple code to mock concurrency using Lock and synchronized.

源码如下:

任务类包含一个名为 doSomething() 的方法,用于打印线程名称和执行经过的时间.

Task class includes a method named doSomething() to print the thread name and executing elapsed time.

import java.util.Calendar;

public class Task {
    public void doSomething() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        StringBuilder sb = new StringBuilder();
        //Thread Name
        sb.append("Thread Name: ").append(Thread.currentThread().getName());

        //Timestamp  for the executing
        sb.append(", elaspsed time: ").append(Calendar.getInstance().get(13)).append(" s ");
        System.out.println(sb.toString());
    }
}

TaskWithLock 类

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TaskWithLock extends Task implements Runnable {
    private final Lock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lock();
            doSomething();
        } finally {
            lock.unlock();
        }

    }
}

TaskWithSync 类

public class TaskWithSync extends Task implements Runnable {

    @Override
    public void run() {
        synchronized ("A") {
            doSomething();
        }
    }
}

主类

public class Main {
    public static void runableTasks(Class<? extends Runnable> clz)
            throws Exception {
        ExecutorService service = Executors.newCachedThreadPool();

        System.out.printf("<-- Start executing %s Task --> 
",
                clz.getSimpleName());

        // Start 3 threads
        for (int i = 0; i < 3; i++) {
            service.submit(clz.newInstance());
        }

        // Wait for some time, and then close the executor
        TimeUnit.SECONDS.sleep(10);
        System.out
                .printf("<-- %s Tasks is complet --> 
", clz.getSimpleName());
        service.shutdown();
    }

    public static void main(String[] args) throws Exception {
        //Execute tasks with Lock
        runableTasks(TaskWithLock.class);

        //Execute tasks with Synchronized 
        //runableTasks(TaskWithSync.class);
    }
}

第一次,通过调用runableTasks(TaskWithSync.class)方法同步执行任务;

<-- Start executing TaskWithSync Task --> 
Thread Name: pool-1-thread-1, elaspsed time: 28 s 
Thread Name: pool-1-thread-3, elaspsed time: 30 s 
Thread Name: pool-1-thread-2, elaspsed time: 32 s 
<-- TaskWithSync Tasks is complet --> 

第二次,调用方法runableTasks(TaskWithLock.class);

<-- Start executing TaskWithLock Task --> 
Thread Name: pool-1-thread-3, elaspsed time: 23 s 
Thread Name: pool-1-thread-2, elaspsed time: 23 s 
Thread Name: pool-1-thread-1, elaspsed time: 23 s 
<-- TaskWithLock Tasks is complet --> 

上面的例子使用 Locksynchronized 来运行任务,我这里有一些问题:

With the above example using Lock and synchronized to run the tasks, I have some questions here:

Q1: 同步示例中的时间戳,它反映了 3 个线程之间的互斥量.但是为什么 Lock 例子中的经过时间是一样的呢?我不知道为什么.

Q1: The timestamp in the synchronized example, it reflects the mutex between 3 Threads. But why is the elapsed time in Lock example the same? I don't know why.

Q2:在我的例子中synchronizedLock有什么区别?

Q2: What's the difference between synchronized and Lock in my example?

请帮我解决这两个问题.

Please help me out with these 2 questions.

推荐答案

首先,您使用 synchronized 的示例是错误的:在对象A"上同步是一个非常糟糕的主意.请改用以下成语:

First of all, your example using synchronized is ill conceived: it is a very bad idea to synchronize on object "A". Use the following idiom instead:

private final Object lock = new Object();

public void run() {
    synchronized (lock) {
        doSomething();
    }
}

这更好,因为通过对外部对象隐藏您的锁,您可以封装您的同步协议,从而实现更安全的同步策略.

This is better because by hiding your lock from external objects, you are encapsulating your synchronization protocol and thereby implementing a safer synchronization policy.

现在,synchronizedjava.util.concurrent.locks.Lock 之间的区别在于,前者是同步原语,而后者是更高级别的锁定结构它提供了比 synchornized 更精细的操作.

Now, the difference between synchronized and java.util.concurrent.locks.Lock, is that the former is a synchronization primitive whereas the latter a higher level locking construct which provides more elaborate operations than synchornized.

更多信息,您可以查看 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html 和 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/特别是 locks/ReentrantLock.html.

Fore more information you may look at http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html and http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html in particular.

相关文章