黑马程序员技术交流社区
标题:
关于线程问题
[打印本页]
作者:
杨希
时间:
2014-4-8 14:58
标题:
关于线程问题
本帖最后由 杨希 于 2014-4-8 16:26 编辑
跟毕姥爷学习多线程这块的时候,写了一些代码,现在复习的时候有一块有点不明白,求解
/*
多线程卖票程序
*/
class Ticket implements Runnable
{
private int tick = 100;
Object obj = new Object(); //这块为什么要创建Object对象
public void run()
{
while(true)
{
synchronized(obj) //有这个锁的原因
{
if(tick>0)
System.out.println(Thread.currentThread().getName()+"..sale:"+tick--);
}
}
}
}
class ThreadText2
{
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
复制代码
我自己又写了一个,发现能运行,求大家给看看跟上面这个比,有啥弊端
class Demo3
{
public static void main(String args[])
{
Ticket t =new Ticket();
Thread t1 =new Thread(t);
Thread t2 =new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
}
}
class Ticket implements Runnable
{
private int x =20;
public void run()
{
for(int y=0;y<=x;y++)
{
System.out.println(Thread.currentThread().getName()+"sale"+x);
x--;
}
}
复制代码
后来我根据毕姥爷的代码编译了一下,发现我输出的结果都是Thread-0,应该是有3个线程同时进行,我记得毕姥爷说过这个问题,但是我给忘了,大家还记得吗?
Thread-0sale20
Thread-0sale19
Thread-0sale18
Thread-0sale17
Thread-0sale16
Thread-0sale15
Thread-0sale14
Thread-0sale13
Thread-0sale12
Thread-0sale11
Thread-0sale10
Thread-0sale9
Thread-0sale8
Thread-0sale7
Thread-0sale6
Thread-0sale5
Thread-0sale4
Thread-0sale3
Thread-0sale2
Thread-0sale1
作者:
zhangbingyuan
时间:
2014-4-8 15:21
还是得加锁。因为得让for循环具备原子性。
for(int y=0; y<=x; y++)
{
System.out.println(Thread.currentThread().getName()+"sale"+x); ①
x--; ②
}
应该给语句1和2加锁。如果执行到①,线程1被阻塞了。这时候线程2又进来,判断x跟线程1的判断结果一样,线程2执行完毕,假设此时线程3又开始执行for循环,执行结束后,线程2接着执行,总是没有执行到线程1,那么当线程2和线程3将x减为0时,这时候线程1得到了执行权,这时候,在执行下面的语句会发生异常的 。
作者:
chen20134
时间:
2014-4-8 15:23
synchronized 块
ynchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法,有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,直接运行。
通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (可以是类实例或类)的锁方能执行。
在多线程程序的其他部分可能会发生与这个synchronized 代码块同步的代码,这个时候加synchronized() 锁中的对象可以使同一个对象,就可以解决同步带来的问题
你的代码没有synchronized 锁,所以在运行的时候会发生同步的问题,即多个线程同时执行,在不同的情况下会获得不同的结果。加上synchronized 锁后可以安全。
作者:
菠萝鱼
时间:
2014-4-8 15:23
当多线程操作同一个成员变量时,为了安全,需要用static 修饰成员变量,或者在操作这个变量的代码区加上线程安全代码块。否则会出现重复的票值,也有可能出现负数。
作者:
请备注
时间:
2014-4-8 16:40
你定义的数太小了其它线程来不及抢到执行权就结束了
定义100 或1000就能看到多线程了 也能看到安全问题了
而且多线程每次运行结果都 不一样的 多运行几遍。
作者:
刘一博
时间:
2014-4-8 16:59
不加synchronized的话,会出现线程安全问题,你可以将总票数的值设定多一些,然后逐个观察,可以发现在不加锁的情况下,会出现打印的票序混乱
作者:
云行水边
时间:
2014-4-8 17:12
要创建Object对象是为了让synchronized,这是因为synchronized后面需要跟类,所以定义超类来满足语法要求,加锁是为了防止会出现重复的票值,以及负数!!
作者:
╰つ
时间:
2014-4-8 18:06
[b
]第一个问题:为什么都是Thread-0:
因为cpu处理速度太快了,别的线程没有机会进来,它就结束了!您可以试试让它运行一会
第二个问题:就是那个同步代码块?
当多条线程操作同一个共享数据时,就会出现线程安全问题,
还有那个锁,就是用来监视你同步代码块中的线程,如果里面有线程,就不让它进,没有就,就让它进
作者:
清风夜独醉
时间:
2014-4-8 23:06
关于为什么创建Object对象,是因为synchronized后面必须要跟个锁对象,这个锁可以是任意对象,所以创建了这个Object超类的对象。不用这个对象也行,你可以任意创建个对象,比如说代码中Tick类的对象也行。
synchronized如果写在方法上,虽然后面不写锁对象,但是自带的有个默认锁对象,非静态方法锁对象是this,静态方法锁对象是所在类的.class字节码对象。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2