synchronized与Lock的对比
1. Lock是显式锁(手动开启和关闭锁,别忘记关闭锁),synchronized是隐式锁,出了作用域自动释放
2. Lock只有 代码块锁,synchronized有 代码块锁和方法锁
3. 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类
优先使用顺序:
Lock >同阳代码块(已经进入了方法体,分配了相应资源) >同步方法。(在方法体之外)
一:synchronized锁
方式一:同步代码块
synchronized(同步监视器){ //需要被同步的代码 }
说明:
-
操作共享数据的代码,即为需要被同步的代码。--> 不能包合代码多了,也不能包含代码
-
共享数据:多个线程共同操作的变量。比如: ticket就是共享数据。
-
同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
要求:多个线程必须要共用同一把锁。
补充:在实现Runnable按口创建多钱程的方式中,我们可以考虑使用this充当同步监视器。
class MyRunnable implements Runnable {
private static int ticked = 100;
@Override
public void run() {
while (true) {
synchronized (this) {
if (ticked > 0) {
System.out.println(Thread.currentThread().getName() + " : " + ticked + "*****");
ticked--;
}else {
break;
}
}
}
}
}
public class RunnableTest {
public static void main(String[] args) {
//创建实例对象
MyRunnable myRunnable = new MyRunnable();
//将此对象传入Thead类构造器中
Thread t1 = new Thread(myRunnable);
//线程改名
t1.setName("主线程");
//启动线程,调用run方法
t1.start();
Thread t2 = new Thread(myRunnable);
t2.setName("次线程");
t2.start();
}
}
2 方式二,同步方法。
关于同步方法的总结: 1.同步方法仍然涉及到同步监视器,只是不需要我们显 式的声明。 2.非静态的同步方法,同步监视器是: this 静态的同步方法,同步监视器是:当前类本身
二 Lock锁
class Window implements Runnable {
private static int ticket = 100;
//实例化ReentrantLock锁接口
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
//锁开启
lock.lock();
try {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "买票,票号为:" + ticket);
ticket--;
} else {
break;
}
} finally {
//锁关闭
lock.unlock();
}
}
}
}
public class WindowTest {
public static void main(String[] args) {
Window window = new Window();
Thread t1 = new Thread(window);
Thread t2 = new Thread(window);
Thread t3 = new Thread(window);
t1.setName("窗口一:");
t2.setName("窗口二:");
t3.setName("窗口三:");
t1.start();
t2.start();
t3.start();
}
}