版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gao23191879/article/details/75123213
学过操作系统的人都知道前驱图是一个很好用来描述多个进程或线程间的同步执行的过程
科普一下同步的概念:同步是用来描述多个并发线程或进程按某种规则共享系統资源,并能很好的相互协作,使程序执行具有可再现性。
首先我们来看一下最简单的前趋图
java如何实现了
有俩种方式
第一种基于Lock+Condition方式
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
ExecutorService es=Executors.newFixedThreadPool(4);
final Lock lock=new ReentrantLock();
final Condition s=lock.newCondition();
es.execute(new Runnable(){
@Override
public void run() {
lock.lock();
try{
try {
s.await();
System.out.println("我是p2线程 ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}finally{
lock.unlock();
}
}
});
es.execute(new Runnable(){
@Override
public void run() {
lock.lock();
try{
System.out.println("我是p1线程");
s.signal();
}finally{
lock.unlock();
}
}
});
}
}
第二种基于java 计数信号量 Semaphore
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Test3 {
public static void main(String[] args) {
ExecutorService es=Executors.newFixedThreadPool(4);
final Semaphore s=new Semaphore(0,true);
es.execute(new Runnable(){
@Override
public void run() {
try {
s.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是p2线程");
}
});
es.execute(new Runnable(){
@Override
public void run() {
System.out.println("我是p1线程");
s.release();
}
});
}
}
下面我们来看一下复杂的前趋图
根据操作系统知识可知 该前趋图的执行过程可以为:
p1->p2->p3->p4->p5->p6
定义7个信号量 :a,b,c,d,e,f,g都初始化为0
对应的处理任务为:s1->s2->s3->s4->s5->s6
p1={ s1 ; single(a); single(b) }
p2={ waite(a); s2; single(c); single(d) }
p3={ waite(b); s3; single(e) }
p4={ waite(c); s4; single(f); }
p5={ waite(d); s5; single(g); }
p6={ waite(e); waite(f); waite(g); s6;}
以上是操作系统的分析
waite() 时 信号量减一 说明该资源已被申请占用,因为初始化信号量为0 说明只能被一个线程请求使用,如果还有线程请求时将会阻塞,直到占用资源的线程释放该资源,并通知阻塞线程。此时阻塞队列中的线程将就绪,然后开始竞争。
下面我们来看一下java如何实现的
有以上分析可知p6线程需要等待三个信号量的通知才能执行。
而 java 条件监听机制 Condtion 一个线程只能等待一个通知信号,不能同时等待多个通知信号。
所以我们用java的计数信号量 Semaphore来实现
Semaphroe 类中有两方法 一个是 acquire() 等同于 waite()
release() 等同于 single()
下面我们来看一下代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class Test2 {
public static void main(String[] args) {
ExecutorService es=Executors.newFixedThreadPool(10);
final Semaphore a=new Semaphore(0,true);
final Semaphore b=new Semaphore(0,true);
final Semaphore c=new Semaphore(0,true);
final Semaphore d=new Semaphore(0,true);
final Semaphore e=new Semaphore(0,true);
final Semaphore f=new Semaphore(0,true);
final Semaphore g=new Semaphore(0,true);
es.execute(new Runnable(){
@Override
public void run() {
try {
a.acquire();
System.out.println("我来自S2");
c.release();
d.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
es.execute(new Runnable(){
@Override
public void run() {
try {
e.acquire();
f.acquire();
g.acquire();
System.out.println("我来自S6");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
es.execute(new Runnable(){
@Override
public void run() {
System.out.println("我来自S1");
a.release();
b.release();
}
});
es.execute(new Runnable(){
@Override
public void run() {
try {
b.acquire();
System.out.println("我来自S3");
e.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
es.execute(new Runnable(){
@Override
public void run() {
try {
c.acquire();
System.out.println("我来自S4");
f.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
es.execute(new Runnable(){
@Override
public void run() {
try {
d.acquire();
System.out.println("我来自S5");
g.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
执行结果如下
好了博客写完了,你有没有涨知识了。