Java 什么';在我的例子中,Synchronized和Lock的区别是什么?

Java 什么';在我的例子中,Synchronized和Lock的区别是什么?,java,multithreading,synchronization,locking,Java,Multithreading,Synchronization,Locking,我使用Lock和synchronized编写了一个模拟并发的简单代码 源代码如下: 任务类包括一个名为doSomething()的方法,用于打印线程名称和执行所用时间 import java.util.Calendar; public class Task { public void doSomething() { try { Thread.sleep(2000); } catch (InterruptedException e)

我使用
Lock
synchronized
编写了一个模拟并发的简单代码

源代码如下:

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

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());
    }
}
带锁任务

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 --> \n",
                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 --> \n", 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);
    }
}
Main

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 --> \n",
                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 --> \n", 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);
    }
}
公共类主{

public static void runableTasks(Class首先,您使用
synchronized
的示例构思不周:在对象“a”上同步是一个非常糟糕的主意。请改用以下习惯用法:

private final Object lock = new Object();

public void run() {
    synchronized (lock) {
        doSomething();
    }
}
这会更好,因为通过对外部对象隐藏锁,可以封装同步协议,从而实现更安全的同步策略

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

您可以查看更多信息,尤其是

synchronized ("A")
这不是同步块的正确用法。在某些情况下,您在进入此同步块时创建了不同的字符串对象,因此每个线程都有不同的锁定对象,因此不同步。正确用法可能如下

synchronized(this)


此外,您应该在不同的线程中使用一个可运行的实现,或者将您的锁设置为静态字段

私有最终锁
应该是
静态的
,或者每个线程都有自己的锁,这使得锁基本上没有用处。在
尝试之前,也可以使用
.lock()
{
最后
部分将尝试解锁未锁定的锁(以防
.lock()
引发异常)@zapl通过使锁为静态,在任何实例上调用该方法,也会阻止所有其他方法调用,无论它们是否在不同的对象实例上调用。这肯定不是一个有效的锁定策略。@lefty此测试是(据我所见)尝试测试由多个实例共享的锁。如果每个线程都有自己的锁,则根本不需要同步的锁(此处为threads=instances),因为它不封装同步策略,因为其他对象可能“无意”获取锁。
public class TaskWithSync extends Task implements Runnable {
    private Object lock = new Object();

    @Override
    public void run() {

        synchronized (lock) {
            doSomething();
        }
    }
}