黑马程序员技术交流社区

标题: 多线程中同步代码块问题 [打印本页]

作者: zhangfeng    时间: 2012-6-22 21:10
标题: 多线程中同步代码块问题
本帖最后由 zhangfeng 于 2012-6-23 09:47 编辑

在多线程中,什么时候要用到同步代码块,同步代码块的具体作用是什么
作者: 丁二跃    时间: 2012-6-22 21:19
51、同步和异步有何异同,在什么情况下分别使用他们?举例说明。

     如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

     当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。



--------摘自 《张孝祥java就业面试宝典》
作者: 丁二跃    时间: 2012-6-22 21:24
最经典的例子:一个帐号有500,我在这边要取500,我发出指令,银行把钱给我,但数据还没变时你在那边也取500…………什么后果?银行赔死了

所以这个时候就要同步了,我取钱的时候你不能取,你取钱的时候我不能取
作者: 潘东升    时间: 2012-6-22 21:26
哥们,老毕视频很详细,你懂的
作者: 张文强    时间: 2012-6-22 21:34
多窗口售票,为了保证不会出现重复票、错票
作用就是为了解决多线程运行时出现的安全性问题。
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
作者: 伊文龙    时间: 2012-6-22 21:55
同步解决的是线程安全的问题。当你访问一个资源的时候,防止其他线程和你同时访问,造成的数据安全的问题。

另外,4楼哥们正解。去看毕老师视频你懂得
作者: 张华廷    时间: 2012-6-22 22:00

简单的说就是为了解决多线程运行时出现的安全性问题。
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
java对于多线程的安全性问题提供了专业的解决方式。就是同步代码块。
synchronized(对象)
{
        需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行,没有持有锁的线程,即使获取了CPU的执行权也进不去,因为没有获取锁。

作者: 孙浩迪    时间: 2012-6-22 22:13
//不加同步控制
public class ThreadDemo1 {
        public static void main(String[] args) {
               
                TestThread tt = new TestThread();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
               
        }
}

class TestThread implements Runnable{
        private int tickets = 100;
        public void run(){
                while(true){
                        if(tickets>0){//如果thread1执行到这被thread2抢了时间片就有了同步问题
                                try {
                                        Thread.sleep(10);
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                                System.out.println(Thread.currentThread().getName()+" is sailing ticket " + tickets--);
                        }
                }
        }
}


//result
//Thread-0 is sailing ticket 5
//Thread-3 is sailing ticket 4
//Thread-2 is sailing ticket 3
//Thread-4 is sailing ticket 2
//Thread-1 is sailing ticket 1
//Thread-2 is sailing ticket 0
//Thread-3 is sailing ticket -1
//Thread-0 is sailing ticket -2
//Thread-4 is sailing ticket –3加同步控制
package myk;


public class ThreadDemo1 {
        public static void main(String[] args) {
               
                TestThread tt = new TestThread();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
               
        }
}

class TestThread implements Runnable{
        private int tickets = 20;
       
        String str = new String("");
       
        public void run(){//String str = new String(""); 如果把标志位放这则起不到同步的效果                while(true){
                        synchronized (str) {//标志位对象,该标志位具有0,1两种状态,当有线程执行这块代码时,就把标志位置为0,执行完后就把标志为置为1这个标志叫锁旗标,一个用于synchronized语句中的对象称为一个监视器,当一个线程获得了synchronized(object)语句中的代码块的执行权,意味着锁定了监视器同步处理后,程序运行速度会减慢,因为系统不停的对同步监视器进行检查
                                if(tickets>0){
                                        try {
                                                Thread.sleep(10);
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                        System.out.println(Thread.currentThread().getName()+" is sailing ticket " + tickets--);
                                }
                        }
                }
        }
}


//result
//Thread-0 is sailing ticket 20
//Thread-1 is sailing ticket 19
//Thread-2 is sailing ticket 18
//Thread-3 is sailing ticket 17
//Thread-4 is sailing ticket 16
//Thread-0 is sailing ticket 15
//Thread-1 is sailing ticket 14
//Thread-2 is sailing ticket 13
//Thread-3 is sailing ticket 12
//Thread-4 is sailing ticket 11
//Thread-0 is sailing ticket 10
//Thread-1 is sailing ticket 9
//Thread-2 is sailing ticket 8
//Thread-3 is sailing ticket 7
//Thread-4 is sailing ticket 6
//Thread-0 is sailing ticket 5
//Thread-1 is sailing ticket 4
//Thread-2 is sailing ticket 3
//Thread-3 is sailing ticket 2
//Thread-4 is sailing ticket 1同步函数


public class ThreadDemo1 {
        public static void main(String[] args) {
               
                TestThread tt = new TestThread();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
                new Thread(tt).start();
               
        }
}

class TestThread implements Runnable{
        private int tickets = 20;

        public void run(){
               
                while(true){
                        sale();
                }
        }
       
        public synchronized void sale(){
                if(tickets>0){
                        try {
                                Thread.sleep(10);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+" is sailing ticket " + tickets--);
                }       
        }
       
}代码块与函数间的同步

public class ThreadDemo1 {
        public static void main(String[] args) {
               
                TestThread t = new TestThread();
                new Thread(t).start();//调用同步方法  注意这块,启动了线程,不一定马上就执行这个线程
                try {
                        Thread.sleep(3);
                } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                t.str = new String("method");
                new Thread(t).start();//这个线程调用同步代码块
               
               
        }
}

class TestThread implements Runnable{
        private int tickets = 100;
        String str = new String("");
       
        public void run(){
               
                if(str.equals("method")){
                        while(true){
                                sale();
                        }
                }else{
                        synchronized (str) {
                                try {
                                        Thread.sleep(100);//通过Thread.interrupt(),可以打断线程的睡眠,//当然一个线程调用另一个线程的inerrupt,线程的睡眠被打断后进入Runnable状态。
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                                System.out.println(Thread.currentThread().getName()+" is sailing ticket " + tickets--);
                        }
                }
        }
       
        public synchronized void sale(){//同步函数使用的是this监视器
                if(tickets>0){
                        try {
                                Thread.sleep(100);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                        System.out.println("test:");
                        System.out.println(Thread.currentThread().getName()+" is sailing ticket " + tickets--);
                }       
        }
       
}


给你举了2 个例子,  你运行下好好研究下就明白了。
作者: 挥手遗忘    时间: 2012-6-22 23:04
多线程运算的时候  避免线程同时访问同一个资源 。看老毕的视频  上面说的很详细!
作者: 吴小铁你好    时间: 2012-6-22 23:46
简单的说就是为了解决多线程运行时出现的安全性问题。
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
java对于多线程的安全性问题提供了专业的解决方式。就是同步代码块。
synchronized(对象)
{
        需要被同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行,没有持有锁的线程,即使获取了CPU的执行权也进不去,因为没有获取锁。
作者: zhangfeng    时间: 2012-6-23 09:47
sunhaodi 发表于 2012-6-22 22:13
//不加同步控制
public class ThreadDemo1 {
        public static void main(String[] args) {

谢了,我自己理解理解




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2