有关线程互斥与同步面试题
来源:互联网 发布:定做软件要多少钱 编辑:程序博客网 时间:2024/05/04 06:12
一.一道经典的面试题
- 关于线程的同步通信和互斥,我们可以用一道面试题来说明和检测,如下
子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次
- 我们先实现子线程和主线程循环的代码
new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++) { for(int j=1;j<=10;j++) { System.out.println("sub thread sequece of "+j+",loop of "+i); } } } }).start(); for(int i=1;i<=50;i++) { for(int j=1;j<=100;j++) { System.out.println("main thread sequece of "+j+",loop of "+i); } }
- 显然此时连互斥还没实现
- 于是我们加上线程互斥
new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++) { synchronized (TraditionalThreadCommunicationTest.class) { for(int j=1;j<=10;j++) { System.out.println("sub thread sequece of "+j+",loop of "+i); } } } } }).start(); for(int i=1;i<=50;i++) { synchronized (TraditionalThreadCommunicationTest.class) { for(int j=1;j<=100;j++) { System.out.println("main thread sequece of "+j+",loop of "+i); } } }
虽然此时互斥不会有问题,但是并没有实现子线程一下,主线程一下的效果(即相互通信)
而且还有一个重要的问题:上面这个代码真的好嘛???真的准确嘛???
即使对于已经实现的功能来说,上面的代码也还有很多的问题
a.因为字节码文件只有一份,所以我们经常把它当成锁对象,但是这样真的好嘛?
- 如果你项目很大,很复杂,要你分为A,B两组,A要同步,B也要同步,如果此时动用字节码文件来当锁对象,其中的同步块就变成一组了,所以此时是不能用其当锁对象,把字节码文件当锁对象,一定要慎之又慎!!!
b.我们要学会面向对象的思维的设计,应该要把相类似的方法放到一个类去,这样更容易维护一些,所以…
public class TraditionalThreadCommunicationTest { public static void main(String[] args) { Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++) { business.sub(i); } } }).start(); for(int i=1;i<=50;i++) { business.main(i); } }} class Business{ public synchronized void sub(int i) { for(int j=1;j<=10;j++) { System.out.println("sub thread sequece of "+j+",loop of "+i); } } public synchronized void main(int i) { for(int j=1;j<=100;j++) { System.out.println("main thread sequece of "+j+",loop of "+i); } } }
当然这个和前一个代码功能一样的,也是互斥做到了,但是相互通信没有做到
我们要用一个boolean值来进行下面的相互通信操作
public class TraditionalThreadCommunicationTest { public static void main(String[] args) { Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++) { business.sub(i); } } }).start(); for(int i=1;i<=50;i++) { business.main(i); } }} class Business{ private boolean flag=true; public synchronized void sub(int i) { if(!flag) {//如果为false,此时线程等待 try { this.wait();//线程等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for(int j=1;j<=10;j++) { System.out.println("sub thread sequece of "+j+",loop of "+i); } flag=false; this.notify();//唤醒等待的线程 } public synchronized void main(int i) { if(flag) {//为true,此时线程等待 try { this.wait();//线程等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for(int j=1;j<=100;j++) { System.out.println("main thread sequece of "+j+",loop of "+i); } flag=true; this.notify();//唤醒等待的线程 } }
这样就实现了上面的要求,基本没有问题了
但是上面的代码还是有一些小小的问题
- 有时候,线程并没有收到通知就被唤醒,所以此时用if并不好,可以把if改为while
- 效果和if一样,但是比if更牢靠,更健壮
public class TraditionalThreadCommunicationTest { public static void main(String[] args) { Business business = new Business(); new Thread(new Runnable() { @Override public void run() { for(int i=1;i<=50;i++) { business.sub(i); } } }).start(); for(int i=1;i<=50;i++) { business.main(i); } }} class Business{ private boolean flag=true; public synchronized void sub(int i) { while(!flag) { try { this.wait();//线程等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for(int j=1;j<=10;j++) { System.out.println("sub thread sequece of "+j+",loop of "+i); } flag=false; this.notify();//唤醒等待的线程 } public synchronized void main(int i) { while(flag) { try { this.wait();//线程等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } for(int j=1;j<=100;j++) { System.out.println("main thread sequece of "+j+",loop of "+i); } flag=true; this.notify();//唤醒等待的线程 } }
阅读全文
0 0
- 有关线程互斥与同步面试题
- 线程面试题之三:父子线程和子线程之间的同步与互斥
- 线程同步与互斥
- 线程互斥与同步
- 线程同步与互斥
- 线程同步与互斥
- 线程同步与互斥
- 线程同步与互斥
- 线程同步与互斥
- 线程互斥与线程同步
- BCB线程的互斥与同步
- 操作系统 进程/线程 同步与互斥
- 线程同步与互斥 synchronized()
- 三线程的互斥与同步
- 线程的同步与互斥
- Windows线程的同步与互斥
- 线程同步与互斥的总结
- linux线程互斥与同步---互斥锁
- Borg Maze POJ
- Mybatis(四)映射文件
- java项目经验
- 布局
- 法线向量如何归一化(Normalize)
- 有关线程互斥与同步面试题
- java jni 调用c语言函数
- Shuffle'm Up POJ
- eclipse热键
- 异常一般形式
- swipe.js插件相关用法
- 2.神经网络的监督学习
- ubuntu 16.04LTS 下Code::Blocks 16.01 安装
- 第6章gp_toolkit管理架构_gp_bloat_diag