排他鎖和共享鎖:
讀寫鎖:既是排他鎖,又是共享鎖。讀鎖,共享鎖,寫鎖:排他鎖
讀和讀是不互斥的
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Demo {
private Map<String, Object> map=new HashMap<>();
private ReadWriteLock rwl=new ReentrantReadWriteLock();
private Lock r=rwl.readLock();
private Lock w=rwl.writeLock();
public Object get(String key){
r.lock();
System.out.println(Thread.currentThread().getName()+"讀操作正在執行。。。");
try {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return map.get(key);
} finally{
r.unlock();
System.out.println(Thread.currentThread().getId()+"讀操作執行完畢。。。");
}
}
public void put(String key,Object value){
w.lock();
System.out.println(Thread.currentThread().getName()+"寫操作在執行。。。");
try {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
} finally {
w.unlock();
System.out.println(Thread.currentThread().getName()+"寫操作執行完畢。。。");
}
}
}
public class Main {
public static void main(String[] args) {
Demo d=new Demo();
d.put("key1", "value1");
// new Thread(new Runnable() {
// @Override
// public void run() {
// d.put("key1", "value1");
// }
// }).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(d.get("key1"));
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(d.get("key1"));
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(d.get("key1"));
}
}).start();
// new Thread(new Runnable() {
// @Override
// public void run() {
// d.put("key3", "value3");
// }
// }).start();
}
}
讀寫鎖需要保存的狀態:
寫鎖重入的次數
讀鎖的個數
每個讀鎖重入的次數
鎖降級:是指寫鎖降為讀鎖
在寫鎖沒有釋放的時候,獲取到讀鎖,在釋放寫鎖
鎖升級:
把讀鎖,升級為寫鎖
在讀鎖沒有釋放的時候,獲取到寫鎖,在釋放讀鎖
private volatile boolean isUpdate;
public void readWrite(){
r.lock();
if(isUpdate){
r.unlock();
w.lock();
map.put("XXX", "xxx");
r.lock();
w.unlock();
}
Object obj=map.get("XXX");
System.out.println(obj);
r.unlock();
}
出現線程安全性問題的條件
1.必須在多線程的環境下
2.必須有共享資源
3.對共享資源進行非原子性操作
解決線程安全性問題的途徑
1.synchronized 相對慢(偏向鎖、輕量級鎖、重量級鎖)
2.volatile(只能保證讀寫操作,不能保證非原子性操作)
3.JDK提供的原子類
4.使用Lock(共享鎖、排它鎖)
認識的“*鎖“
1.偏向鎖
2.輕量級鎖
3.重量級鎖
4.重入鎖
5.自旋鎖
6.共享鎖
7.獨占鎖
8.排它鎖
9.讀寫鎖
10.公平鎖
11.非公平鎖
12.死鎖
13.活鎖
public class Tmall {
public int count;
public final int MAX_COUNT=10;
public synchronized void push(){
while(count>=MAX_COUNT)
try {
System.out.println(Thread.currentThread().getName()+
"庫存數量達到上限,生產者停止生產。");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count++;
System.out.println(Thread.currentThread().getName()
+"生產者生產,當前庫存為:"+count);
notify();
}
public synchronized void task(){
while(count<=0)
try {
System.out.println(Thread.currentThread().getName()+
"庫存數量為零,消費着等待。");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+
"消費者消費,當前庫存為:"+count);
notify();
}
}
public class TaskTarget implements Runnable {
private Tmall tmall;
public TaskTarget(Tmall tmall) {
this.tmall=tmall;
}
@Override
public void run() {
tmall.task();
}
}
public class PushTarget implements Runnable{
private Tmall tmall;
public PushTarget(Tmall tmall) {
this.tmall=tmall;
}
@Override
public void run() {
while(true){
tmall.push();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args){
Tmall tmall=new Tmall();
PushTarget p=new PushTarget(tmall);
TaskTarget t=new TaskTarget(tmall);
new Thread(p).start();
new Thread(p).start();
new Thread(p).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
Condition的使用。
public class Demo5 {
private int signal;
//執行順序 a->b->c
public synchronized void a(){
while(signal!=0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("a");
signal++;
notifyAll();
}
public synchronized void b(){
while(signal!=1){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("b");
signal++;
notifyAll();
}
public synchronized void c(){
while(signal!=2){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("c");
signal=0;
notifyAll();
}
public static void main(String[] args){
Demo5 d=new Demo5();
A a=new A(d);
B b=new B(d);
C c=new C(d);
new Thread(a).start();
new Thread(b).start();
new Thread(c).start();
}
}
class A implements Runnable{
private Demo5 demo;
public A(Demo5 demo){
this.demo=demo;
}
@Override
public void run(){
while(true){
demo.a();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class B implements Runnable{
private Demo5 demo;
public B(Demo5 demo){
this.demo=demo;
}
@Override
public void run(){
while(true){
demo.b();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class C implements Runnable{
private Demo5 demo;
public C(Demo5 demo){
this.demo=demo;
}
@Override
public void run(){
while(true){
demo.c();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
用condition
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
private int signal;
Lock lock = new ReentrantLock();
Condition a = lock.newCondition();
Condition b = lock.newCondition();
Condition c = lock.newCondition();
public void a() {
lock.lock();
while(signal != 0 ) {
try {
a.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("a");
signal ++;
b.signal();
lock.unlock();
}
public void b() {
lock.lock();
while(signal != 1) {
try {
b.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("b");
signal ++;
c.signal();
lock.unlock();
}
public void c () {
lock.lock();
while(signal != 2) {
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("c");
signal = 0;
a.signal();
lock.unlock();
}
public static void main(String[] args) {
Demo d = new Demo();
A a = new A(d);
B b = new B(d);
C c = new C(d);
new Thread(a).start();
new Thread(b).start();
new Thread(c).start();
}
}
class A implements Runnable {
private Demo demo;
public A(Demo demo) {
this.demo = demo;
}
@Override
public void run() {
while(true) {
demo.a();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class B implements Runnable {
private Demo demo;
public B(Demo demo) {
this.demo = demo;
}
@Override
public void run() {
while(true) {
demo.b();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class C implements Runnable {
private Demo demo;
public C(Demo demo) {
this.demo = demo;
}
@Override
public void run() {
while(true) {
demo.c();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
實現一個隊列:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyQueue<E> {
private Object[] obj;
private int addIndex;
private int removeIndex;
private int queueSize;
private Lock lock=new ReentrantLock();
Condition addCondition=lock.newCondition();
Condition removeCondition=lock.newCondition();
public MyQueue(int count){
obj=new Object[count];
}
public void add(E e){
lock.lock();
//滿了之后等待
while(queueSize==obj.length){
try {
addCondition.await();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
obj[addIndex]=e;
if(++addIndex==obj.length){ //先比較在++
addIndex=0;
}
queueSize++;
removeCondition.signal();
lock.unlock();
}
public void remove(){
lock.lock();
while (queueSize==0) {
try {
removeCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
obj[removeIndex]=null;
if(++removeIndex==obj.length){
removeIndex=0;
}
queueSize--;
addCondition.signal();
lock.unlock();
}
}
