L*****1 发帖数: 34 | 1 昨天面试一家公司被问到一道multithread的问题,本身感觉不难,但是因为这方面经
验不多,想问问各位有没有什么好的解决办法。
给两个method:
void functionFoo() {
while(1){
System.out.print("Foo");
}
}
void functionBar() {
while(1) {
System.out.print("Bar");
}
}
然后两个thread,一个call functionFoo, 一个call functionBar,然后需要你修改这
两个方程来实现输出比如1000行"FooBar"
本人一开始直接用volatile,存一个flag,类似于static一样然后1的时候才输出Foo并
改为2,2的时候输出Bar并改为1。但是面试官说会有busy waiting,问怎么解决busy
waiting,尝试用wait()和notify()结果写出了deadlock。请问各位有什么java里面的
解决办法?谢谢! |
c*******e 发帖数: 621 | 2 感觉wait()和notify()没错啊
为啥会deadlock? |
l*****a 发帖数: 14598 | 3 Semaphore sem1=new Semaphore(1);
Semaphore sem2=new Semaphore(0);
void functionFoo() {
while(1){
sem1.acquire();
System.out.print("Foo");
sem2.release();
}
}
void functionBar() {
while(1) {
sem2.acquire();
System.out.print("Bar");
sem1.release();
}
} |
c*******e 发帖数: 621 | 4 而且我记得linux下你用个普通lock其实是用posix的semaphore,所以跟wait差不多?
除非你特意用spinlock才是busy waiting? |
t**********h 发帖数: 2273 | 5 大牛最后去哪了?
【在 l*****a 的大作中提到】 : Semaphore sem1=new Semaphore(1); : Semaphore sem2=new Semaphore(0); : void functionFoo() { : while(1){ : sem1.acquire(); : System.out.print("Foo"); : sem2.release(); : } : } : void functionBar() {
|
v***o 发帖数: 287 | 6 volitle 不能保证thread safe,只能保证不是cached的value.
【在 L*****1 的大作中提到】 : 昨天面试一家公司被问到一道multithread的问题,本身感觉不难,但是因为这方面经 : 验不多,想问问各位有没有什么好的解决办法。 : 给两个method: : void functionFoo() { : while(1){ : System.out.print("Foo"); : } : } : void functionBar() { : while(1) {
|
s*i 发帖数: 5025 | 7 这个可以吗?
Object b = new Object();
boolean foo = false;
void functionFoo() {
while(1){
synchronized(b) {
if(foo) b.wait();
System.out.print("Foo");
foo = true;
b.notify();
}
}
}
void functionBar() {
while(1) {
synchronized(b) {
if(!foo) b.wait();
System.out.print("Bar");
foo = false;
b.notify();
}
}
}
【在 L*****1 的大作中提到】 : 昨天面试一家公司被问到一道multithread的问题,本身感觉不难,但是因为这方面经 : 验不多,想问问各位有没有什么好的解决办法。 : 给两个method: : void functionFoo() { : while(1){ : System.out.print("Foo"); : } : } : void functionBar() { : while(1) {
|
s*i 发帖数: 5025 | 8 Elegant!
【在 l*****a 的大作中提到】 : Semaphore sem1=new Semaphore(1); : Semaphore sem2=new Semaphore(0); : void functionFoo() { : while(1){ : sem1.acquire(); : System.out.print("Foo"); : sem2.release(); : } : } : void functionBar() {
|
c*******e 发帖数: 621 | 9 其实volatile bool就是thread safe的,不是吗?
thread safe是说get和set都按你的要求完成,不会出现undefined behavior的情况
比如int,你一个thread去set 1,另一个去set 2,结果int里可能变成3,这叫不
threadsafe
而如果一个volatile bool, 如果一个thread去set 1,另一个去set 0,结果不是0,就
是1
如果一个volatile bool, 如果一个thread去set 1,另一个也去set 1,结果只能是1
我觉得volatile bool就是thread safe,只不过它的threadsafety很难帮助你在不用
lock的情况下使你整个程序thread safe,因为如下的case
volatile boolean b;
void foo() {
if( b ) {
//Here another thread might have already changed the value of b to
false
b = false;
}
}
http://stackoverflow.com/questions/4876122/volatile-boolean-vs-
【在 v***o 的大作中提到】 : volitle 不能保证thread safe,只能保证不是cached的value.
|
L*****1 发帖数: 34 | 10 对我就是想出这个办法,但是说这样的话会有busy wait,要一直check if statement
,然后印度哥就问有啥更好办法没有。。用wait+notify怎么组合搞出来都是deadlock.
..
【在 c*******e 的大作中提到】 : 其实volatile bool就是thread safe的,不是吗? : thread safe是说get和set都按你的要求完成,不会出现undefined behavior的情况 : 比如int,你一个thread去set 1,另一个去set 2,结果int里可能变成3,这叫不 : threadsafe : 而如果一个volatile bool, 如果一个thread去set 1,另一个去set 0,结果不是0,就 : 是1 : 如果一个volatile bool, 如果一个thread去set 1,另一个也去set 1,结果只能是1 : 我觉得volatile bool就是thread safe,只不过它的threadsafety很难帮助你在不用 : lock的情况下使你整个程序thread safe,因为如下的case : volatile boolean b;
|
|
|
L*****1 发帖数: 34 | 11 大牛能解释一下嘛?
查了一下Semaphore可以用来创建critical section,但是为啥第二个sem2是0个permit
呢?
求屡一下思路 ~
【在 l*****a 的大作中提到】 : Semaphore sem1=new Semaphore(1); : Semaphore sem2=new Semaphore(0); : void functionFoo() { : while(1){ : sem1.acquire(); : System.out.print("Foo"); : sem2.release(); : } : } : void functionBar() {
|
l*****a 发帖数: 14598 | 12 sem2=0 确保一上来block
sem1=1 确保第一次不会block
require就是-1
release就是+1
permit
【在 L*****1 的大作中提到】 : 大牛能解释一下嘛? : 查了一下Semaphore可以用来创建critical section,但是为啥第二个sem2是0个permit : 呢? : 求屡一下思路 ~
|
L*****1 发帖数: 34 | 13 求教一下,也就是说se2 = new Semaphore(0)仍然还是只有一个permit,只是初始为0?
不过查java doc只有两种构造函数:
Semaphore(int permits)
Creates a Semaphore with the given number of permits and nonfair fairness
setting.
Semaphore(int permits, boolean fair)
Creates a Semaphore with the given number of permits and the given fairness
setting.
难道sem2 = 0不是说0个permit?
求指正。
【在 l*****a 的大作中提到】 : sem2=0 确保一上来block : sem1=1 确保第一次不会block : require就是-1 : release就是+1 : : permit
|
v***o 发帖数: 287 | 14 这个与compiler 有关系,很多C/C++ 不能保证memory barrier on 多线程。对于java
compiler来说,它加上了memory barrier,是thread safe.
【在 c*******e 的大作中提到】 : 其实volatile bool就是thread safe的,不是吗? : thread safe是说get和set都按你的要求完成,不会出现undefined behavior的情况 : 比如int,你一个thread去set 1,另一个去set 2,结果int里可能变成3,这叫不 : threadsafe : 而如果一个volatile bool, 如果一个thread去set 1,另一个去set 0,结果不是0,就 : 是1 : 如果一个volatile bool, 如果一个thread去set 1,另一个也去set 1,结果只能是1 : 我觉得volatile bool就是thread safe,只不过它的threadsafety很难帮助你在不用 : lock的情况下使你整个程序thread safe,因为如下的case : volatile boolean b;
|
p*****2 发帖数: 21240 | 15 用agent就可以了吧
【在 L*****1 的大作中提到】 : 昨天面试一家公司被问到一道multithread的问题,本身感觉不难,但是因为这方面经 : 验不多,想问问各位有没有什么好的解决办法。 : 给两个method: : void functionFoo() { : while(1){ : System.out.print("Foo"); : } : } : void functionBar() { : while(1) {
|
s*i 发帖数: 5025 | 16 二爷能不能展开说说?
【在 p*****2 的大作中提到】 : 用agent就可以了吧
|
l*****a 发帖数: 14598 | 17 0 permit所以block,所以不会先输出bar阿
0?
fairness
【在 L*****1 的大作中提到】 : 求教一下,也就是说se2 = new Semaphore(0)仍然还是只有一个permit,只是初始为0? : 不过查java doc只有两种构造函数: : Semaphore(int permits) : Creates a Semaphore with the given number of permits and nonfair fairness : setting. : Semaphore(int permits, boolean fair) : Creates a Semaphore with the given number of permits and the given fairness : setting. : 难道sem2 = 0不是说0个permit? : 求指正。
|
L*****1 发帖数: 34 | 18 我的意思是0个permit,那在functionFoo里面sem.releae()不是也会导致foo这个
thread变成sleep,0个permit难道也能release和acquire嘛?因为没有permit不是吗?
不好意思不太熟悉这个...
【在 l*****a 的大作中提到】 : 0 permit所以block,所以不会先输出bar阿 : : 0? : fairness
|
p*****2 发帖数: 21240 | 19
想了一下,还是应该用actors
import akka.actor._
case class Foo(times: Int)
case class Bar(times: Int)
case object Foo
case object Bar
class FooActor(barActor: ActorRef) extends Actor {
def receive = {
case Foo(times) if times>0 =>
print(Foo)
barActor ! Bar(times)
}
}
class BarActor() extends Actor {
def receive = {
case Bar(times) =>
println(Bar)
sender ! Foo(times-1)
}
}
object test extends App{
val system = ActorSystem()
val barActor = system.actorOf(Props(new BarActor()))
val fooActor = system.actorOf(Props(new FooActor(barActor)))
fooActor ! Foo(10)
}
【在 s*i 的大作中提到】 : 二爷能不能展开说说?
|
s*i 发帖数: 5025 | 20 传说中的scala?不如java通俗易懂啊
【在 p*****2 的大作中提到】 : : 想了一下,还是应该用actors : import akka.actor._ : case class Foo(times: Int) : case class Bar(times: Int) : case object Foo : case object Bar : class FooActor(barActor: ActorRef) extends Actor { : def receive = { : case Foo(times) if times>0 =>
|
|
|
d**e 发帖数: 6098 | |
t**********h 发帖数: 2273 | |
l*****a 发帖数: 14598 | 23 看了我的solution你还能给ship it?
【在 d**e 的大作中提到】 : 好工整.Ship It!
|
t**********h 发帖数: 2273 | 24 sheep it
【在 l*****a 的大作中提到】 : 看了我的solution你还能给ship it?
|
g**e 发帖数: 6127 | 25 都没看出来我写的是错的?
【在 l*****a 的大作中提到】 : 看了我的solution你还能给ship it?
|
l*****a 发帖数: 14598 | 26 一般来说写那么长的基本没人看...
【在 g**e 的大作中提到】 : 都没看出来我写的是错的?
|
d**e 发帖数: 6098 | 27 没看出来.主要是你的ID太耀眼了,就算有问题也覆盖了所有问题.
【在 g**e 的大作中提到】 : 都没看出来我写的是错的?
|
d**e 发帖数: 6098 | 28 你的看不懂,我不敢说一句话.
【在 l*****a 的大作中提到】 : 看了我的solution你还能给ship it?
|
g**e 发帖数: 6127 | 29 也对,哈哈。我只是想写个不用semaphore的,肯定要麻烦点,而且容易写错。这个应
该对了。。。
public class PrintFooBar2 {
public void print(int n) {
AtomicBoolean flag = new AtomicBoolean(true);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Worker("foo", flag, n / 2, true));
exec.execute(new Worker("bar", flag, n / 2, false));
exec.shutdown();
}
public static void main(String[] args) {
new PrintFooBar2().print(6);
}
}
class Worker implements Runnable {
private AtomicBoolean flag;
private boolean signal;
private String str;
private int max;
public Worker(String prtStr, AtomicBoolean flag, int max, boolean signal
) {
this.str = prtStr;
this.flag = flag;
this.max = max;
this.signal = signal;
}
@Override
public void run() {
int i = 0;
while (i++ < max) {
synchronized (flag) {
while (flag.get() != signal) {
try {
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(str);
flag.set(!signal);
flag.notify();
}
}
}
}
【在 l*****a 的大作中提到】 : 一般来说写那么长的基本没人看...
|
s*i 发帖数: 5025 | 30 没怎么写过multithreading程序。不过,学习了gate的几点:
1. 用Executor和worker (thread pool)
2. 用一个function body
3. wait的话,总要catch
【在 d**e 的大作中提到】 : 没看出来.主要是你的ID太耀眼了,就算有问题也覆盖了所有问题.
|
|
|
p*****2 发帖数: 21240 | 31 肯定比java好懂 而且并发效果更好
【在 s*i 的大作中提到】 : 传说中的scala?不如java通俗易懂啊
|
s*i 发帖数: 5025 | 32 fooActor 和 barActor 直觉上应该是对称的函数。scala里面怎么搞出两套东西?
【在 p*****2 的大作中提到】 : 肯定比java好懂 而且并发效果更好
|
x*********n 发帖数: 100 | 33 为什么不用两个lock.写java比较少些,不过概念都一样:
Object lock1 = new Object();
Object lock2 = new Object();
void print12() {
Thread t1 = new Thread() {
public void run() {
print1();
}
};
t1.start();
Thread t2 = new Thread() {
public void run() {
print2();
}
};
t2.start();
synchronized(lock1) {
lock1.notify();
}
}
void print1()
{
for (int i = 0; i < 500; i++) {
synchronized(lock1) {
try {
lock1.wait();
}
catch (Exception e) {}
}
System.out.print("1");
synchronized(lock2) {
lock2.notify();
}
}
}
void print2()
{
for (int i = 0; i < 500; i++) {
synchronized(lock2) {
try {
lock2.wait();
}
catch (Exception e) {}
}
System.out.println("2");
synchronized(lock1) {
lock1.notify();
}
}
} |
s*i 发帖数: 5025 | 34 为啥搞这么复杂?
lolhaha和我的solutions有什么问题吗?
【在 x*********n 的大作中提到】 : 为什么不用两个lock.写java比较少些,不过概念都一样: : Object lock1 = new Object(); : Object lock2 = new Object(); : void print12() { : Thread t1 = new Thread() { : public void run() { : print1(); : } : }; :
|
p*****2 发帖数: 21240 | 35 两个职责有些区别
感觉分成两个更清晰
当然可以写成一个 但是逻辑混杂不一定是好事
【在 s*i 的大作中提到】 : fooActor 和 barActor 直觉上应该是对称的函数。scala里面怎么搞出两套东西?
|
g**e 发帖数: 6127 | 36 1. 现在已经不流行用object做lock了,看看ReentrantLock或StampedLock
2. 没看错的话你这个有dead lock的问题哦,如果print12里的lock1.notify在print1
里的lock1.wait之前执行的话
【在 x*********n 的大作中提到】 : 为什么不用两个lock.写java比较少些,不过概念都一样: : Object lock1 = new Object(); : Object lock2 = new Object(); : void print12() { : Thread t1 = new Thread() { : public void run() { : print1(); : } : }; :
|
p*****2 发帖数: 21240 | 37 lock本身还是太复杂
最好还是能lock free
print1
【在 g**e 的大作中提到】 : 1. 现在已经不流行用object做lock了,看看ReentrantLock或StampedLock : 2. 没看错的话你这个有dead lock的问题哦,如果print12里的lock1.notify在print1 : 里的lock1.wait之前执行的话
|
g**e 发帖数: 6127 | 38 面试的时候哪位大牛可以白板写一个lock free的non blocking queue?照这个写
http://www.cs.rochester.edu/research/synchronization/pseudocode
写lock free代码出错概率更高,我是说java
【在 p*****2 的大作中提到】 : lock本身还是太复杂 : 最好还是能lock free : : print1
|
p*****2 发帖数: 21240 | 39 所以现在做并发java并不是最好的选择
【在 g**e 的大作中提到】 : 面试的时候哪位大牛可以白板写一个lock free的non blocking queue?照这个写 : http://www.cs.rochester.edu/research/synchronization/pseudocode : 写lock free代码出错概率更高,我是说java
|
g**e 发帖数: 6127 | 40 哪个技术做起来最少造轮子最快开发最容易维护用哪个
【在 p*****2 的大作中提到】 : 所以现在做并发java并不是最好的选择
|
|
|
x*********n 发帖数: 100 | 41 嗯,应该用Semaphore就好。原理一样,用两个events. 只是觉得这是个面试问题,想
说用最basic的。
java notify早了,还不能把signal设上等wait用的。加上其他各种限制,觉得java里
面的wait, notify设计的不是一般的差。
print1
【在 g**e 的大作中提到】 : 1. 现在已经不流行用object做lock了,看看ReentrantLock或StampedLock : 2. 没看错的话你这个有dead lock的问题哦,如果print12里的lock1.notify在print1 : 里的lock1.wait之前执行的话
|
s*i 发帖数: 5025 | 42 第一次听说这个ReentrantLock和StampedLock。Java里的东西不少啊!
print1
【在 g**e 的大作中提到】 : 1. 现在已经不流行用object做lock了,看看ReentrantLock或StampedLock : 2. 没看错的话你这个有dead lock的问题哦,如果print12里的lock1.notify在print1 : 里的lock1.wait之前执行的话
|
p*****2 发帖数: 21240 | 43 听起来再说scala
【在 g**e 的大作中提到】 : 哪个技术做起来最少造轮子最快开发最容易维护用哪个
|
g**e 发帖数: 6127 | 44 好维护吗?可能比node好一点?
【在 p*****2 的大作中提到】 : 听起来再说scala
|
p*****2 发帖数: 21240 | 45 好多了 听说过kafka spark吗
【在 g**e 的大作中提到】 : 好维护吗?可能比node好一点?
|
m*****k 发帖数: 731 | 46 wait() should be in while loop
【在 s*i 的大作中提到】 : 这个可以吗? : Object b = new Object(); : boolean foo = false; : void functionFoo() { : while(1){ : synchronized(b) { : if(foo) b.wait(); : System.out.print("Foo"); : foo = true; : b.notify();
|
e********2 发帖数: 495 | 47 献个丑:
import java.util.concurrent.SynchronousQueue;
public class SQTest {
public static void main(String[] args) {
SynchronousQueue sq = new SynchronousQueue();
for(int i = 0; i < 2; ++i)
new Thread(new LSQTask(sq, i)).start();;
}
}
class LSQTask implements Runnable {
int j;
SynchronousQueue sq;
public LSQTask(SynchronousQueue sq, int j){
this.sq = sq;
this.j = j;
}
public void run(){
for(int i = 0; i < 500; ++i){
try {
if(j % 2 == 0){
Thread.sleep(1000);
System.out.print("Foo");
sq.put(0);
}else{
sq.take();
System.out.println("Bar");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
【在 L*****1 的大作中提到】 : 昨天面试一家公司被问到一道multithread的问题,本身感觉不难,但是因为这方面经 : 验不多,想问问各位有没有什么好的解决办法。 : 给两个method: : void functionFoo() { : while(1){ : System.out.print("Foo"); : } : } : void functionBar() { : while(1) {
|
w*****a 发帖数: 166 | 48 多谢大牛分享!
看了下大牛们的分析,超级菜鸟说下自己的理解,整理下思路
首先,给出的程序就是busy checking,因为是while,不停的check,从os的角度,这个
thread是running/ready状态。
就算你用volatile,当一个thread在处理时,os仍然给另一个thread时间片来busy
checking if(volatile),所以他说你这个有busy waiting。
那么这样,我们必须想办法让一个thread处理时,另个个必须sleep(from os: blocked
),那就用lolhaha大牛的semaphore了。
当permit=0时,java并不care permit is >0, or <0,只要有人release, permit +1,
所以才可以synced output.
http://www.coderanch.com/t/504827/threads/java/Semaphores
【在 L*****1 的大作中提到】 : 我的意思是0个permit,那在functionFoo里面sem.releae()不是也会导致foo这个 : thread变成sleep,0个permit难道也能release和acquire嘛?因为没有permit不是吗? : 不好意思不太熟悉这个...
|
e********2 发帖数: 495 | 49 单向的SynchronousQueue更自然些。
blocked
【在 w*****a 的大作中提到】 : 多谢大牛分享! : 看了下大牛们的分析,超级菜鸟说下自己的理解,整理下思路 : 首先,给出的程序就是busy checking,因为是while,不停的check,从os的角度,这个 : thread是running/ready状态。 : 就算你用volatile,当一个thread在处理时,os仍然给另一个thread时间片来busy : checking if(volatile),所以他说你这个有busy waiting。 : 那么这样,我们必须想办法让一个thread处理时,另个个必须sleep(from os: blocked : ),那就用lolhaha大牛的semaphore了。 : 当permit=0时,java并不care permit is >0, or <0,只要有人release, permit +1, : 所以才可以synced output.
|
g*********e 发帖数: 14401 | 50 我感觉这个情形用busy waiting都比用锁效率高 |
|
|
L*****1 发帖数: 34 | 51 理解了,非常感谢!
blocked
【在 w*****a 的大作中提到】 : 多谢大牛分享! : 看了下大牛们的分析,超级菜鸟说下自己的理解,整理下思路 : 首先,给出的程序就是busy checking,因为是while,不停的check,从os的角度,这个 : thread是running/ready状态。 : 就算你用volatile,当一个thread在处理时,os仍然给另一个thread时间片来busy : checking if(volatile),所以他说你这个有busy waiting。 : 那么这样,我们必须想办法让一个thread处理时,另个个必须sleep(from os: blocked : ),那就用lolhaha大牛的semaphore了。 : 当permit=0时,java并不care permit is >0, or <0,只要有人release, permit +1, : 所以才可以synced output.
|
g*********9 发帖数: 1285 | 52 这个才是Java的最佳答案,一帮子都没说到点子上。
【在 e********2 的大作中提到】 : 单向的SynchronousQueue更自然些。 : : blocked
|
g*********9 发帖数: 1285 | 53 用countdownlatch来synchronize就足够了。
【在 L*****1 的大作中提到】 : 昨天面试一家公司被问到一道multithread的问题,本身感觉不难,但是因为这方面经 : 验不多,想问问各位有没有什么好的解决办法。 : 给两个method: : void functionFoo() { : while(1){ : System.out.print("Foo"); : } : } : void functionBar() { : while(1) {
|
m*****k 发帖数: 731 | 54 但用SynchronousQueue还是可能foo, foo, bar
thread2 SynchronousQueue.take() 和 output "bar" 之间可以有 thread 1 output
"foo"
【在 e********2 的大作中提到】 : 单向的SynchronousQueue更自然些。 : : blocked
|
I*******d 发帖数: 108 | 55 如果 System.out.print("Foo");抛出异常的话有一个sem不能release。
【在 s*i 的大作中提到】 : Elegant!
|
y*******r 发帖数: 141 | 56 如果是更多组合循环打印呢? 还是上面那个SynchronousQueue更好?
话说这里用BlockingQueue是跟SynchronousQueue效果一样么?
【在 l*****a 的大作中提到】 : Semaphore sem1=new Semaphore(1); : Semaphore sem2=new Semaphore(0); : void functionFoo() { : while(1){ : sem1.acquire(); : System.out.print("Foo"); : sem2.release(); : } : } : void functionBar() {
|