您的位置:首页 > 编程语言 > Java开发

java多线程 -- 同步鎖

2017-03-30 23:54 113 查看
为了解决多线程安全问题
在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile 。
Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。

隐式锁

synchronized

同步代码块;

同步方法。

显示锁 Lock

jdk 1.5 后:同步锁 Lock 需要通过 lock() 方法上锁,必须通过 unlock() 方法进行释放锁。
ReentrantLock 实现了 Lock 接口,并提供了与synchronized 相同的互斥性和内存可见性。但相较于synchronized 提供了更高的处理锁的灵活性。

Lock使用方式:

Lock lock = new ReentrantLock();
lock.lock();
try {
} finally {
lock.unlock();
}


相关API:

void lock() 获取锁。

void lockInterruptibly() 如果当前线程未被中断,则获取锁。

Condition newCondition() 返回绑定到此 Lock 实例的新 Condition 实例。

boolean tryLock() 仅在调用时锁为空闲状态才获取该锁。

boolean tryLock(long time, TimeUnit unit) 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。

void unlock()释放锁。

不使用锁出现多线程安全问题demo:

package com.company;

public class TestLock {

public static void main(String[] args) {
Ticket ticket = new Ticket();

new Thread(ticket, "1号窗口").start();
new Thread(ticket, "2号窗口").start();
new Thread(ticket, "3号窗口").start();
}

}

class Ticket implements Runnable{

private int tick = 100;

@Override
public void run() {
while(true){
if(tick > 0){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}

System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
}

}
}

}


看出现的问题(截取结果中一部分):

3号窗口 完成售票,余票为:10
1号窗口 完成售票,余票为:8
2号窗口 完成售票,余票为:8
3号窗口 完成售票,余票为:8
2号窗口 完成售票,余票为:7
1号窗口 完成售票,余票为:7
3号窗口 完成售票,余票为:7
1号窗口 完成售票,余票为:6
2号窗口 完成售票,余票为:5
3号窗口 完成售票,余票为:4
3号窗口 完成售票,余票为:3
1号窗口 完成售票,余票为:3
2号窗口 完成售票,余票为:3
3号窗口 完成售票,余票为:2
1号窗口 完成售票,余票为:0
2号窗口 完成售票,余票为:1


现在我们用Lock来进行处理:

package com.company;

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

public class TestLock {

public static void main(String[] args) {
Ticket ticket = new Ticket();

new Thread(ticket, "1号窗口").start();
new Thread(ticket, "2号窗口").start();
new Thread(ticket, "3号窗口").start();
}

}

class Ticket implements Runnable {

private int tick = 100;
private Lock lock = new ReentrantLock();

@Override
public void run() {
while (true) {
try {
lock.lock();
if (tick > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}

System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
}
} finally {
lock.unlock();
}

}
}

}


看下结果(当然也是一部分),很完美解决多线程安全问题:

2号窗口 完成售票,余票为:20
2号窗口 完成售票,余票为:19
2号窗口 完成售票,余票为:18
2号窗口 完成售票,余票为:17
2号窗口 完成售票,余票为:16
2号窗口 完成售票,余票为:15
2号窗口 完成售票,余票为:14
2号窗口 完成售票,余票为:13
2号窗口 完成售票,余票为:12
2号窗口 完成售票,余票为:11
2号窗口 完成售票,余票为:10
2号窗口 完成售票,余票为:9
2号窗口 完成售票,余票为:8
2号窗口 完成售票,余票为:7
2号窗口 完成售票,余票为:6
2号窗口 完成售票,余票为:5
2号窗口 完成售票,余票为:4
2号窗口 完成售票,余票为:3
2号窗口 完成售票,余票为:2
2号窗口 完成售票,余票为:1
2号窗口 完成售票,余票为:0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: