A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 苏小惠 中级黑马   /  2014-1-7 22:01  /  1484 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 苏小惠 于 2014-2-24 18:56 编辑

同步是为了解决线程安全:那具体什么时候用同步代码块,什么时候用同步函数?

评分

参与人数 1技术分 +1 收起 理由
黄晓鑫 + 1

查看全部评分

4 个回复

倒序浏览
同步函数 同步代码块的另一种方式
/*
    需求:
    银行有一个金库。
    有两个储户分别存300元,每次存100,存3次。
   
    目的:给程序是否有安全问题,如果有,如何解决?

    如何找到问题;
    1,明确那些代码是多线程运行代码
    2,明确共享数据,
    3,明确多线程运行代码中些数据是操作共享数据的。
*/

class BankAdd
{
    int num;
    //Object ob=new Object();
    public synchronized void add(int x){//同步函数 同步代码块的另一种方式。
        //(ob){
        num=num+x;
        try{Thread.sleep(10);}catch(Exception e){}
        System.out.println("num="+num);
        //}
    }
}
class Bank implements Runnable
{
    BankAdd ba=new BankAdd();
    public void run(){
        for(int x=0;x<3;x++){
            ba.add(100);
            //System.out.println(Thread.currentThread().getName());
        }
        
    }
}
class  BankTest
{
    public static void main(String[] args)
    {
        Bank b=new Bank();
        Thread t1=new Thread(b);
        Thread t2=new Thread(b);
        t1.start();
        t2.start();

    }
}



评分

参与人数 1技术分 +1 收起 理由
黄晓鑫 + 1

查看全部评分

回复 使用道具 举报
在java中,当同步代码块和同步函数一起使用时,为什么同步代码块的Thread.sleep()时间要小于同步函数,例如售票,当同步函数Thread.sleep()时间中的小于同步代码块时,无论多少售票点,都只能是同一窗口售出2张票......
回复 使用道具 举报
1.同步代码块,使用的锁可以是任意对象,但是操作共享资源时,锁必须唯一!

2.同步函数,使用的锁是this!

package com.gc.thread;

public class SynchronizdMethod implements Runnable {

  //共享资源
  private int num = 1000;
  
  //不同的线程进入不同的同步代码中,验证同步函数使用的锁与同步代码块的锁是否一致
  //如果不一致,则会导致数据混乱!
  boolean flag = true;
  
  @Override
  public void run() {
    if(flag) {
      //改变标记,当b线程开启后,执行run(),就会进入到同步函数中
      flag = false;
      while(true) {
        //同步代码块。判断 num>0 和 num-- 都是对共享资源进行操作,所以要放在同步代码块中
        synchronized(this) {
          //只要本次的同步代码块中的代码没有执行完,其它线程无法进入,因为锁没有释放
          if(num>0)
            System.out.println(Thread.currentThread().getName() + ": code segment--->" + num--);
        }
      }
    } else {
      while(true)
        anotherThread();
    }
  }
  
  //同步函数---使用函数对操作共享资源的代码进行封装,再将锁声明在方法上
        //使用的锁是this,即传入Thread构造函数中的Runnable子类对象
  private synchronized void anotherThread() {
    if(num>0)
      System.out.println(Thread.currentThread().getName() + ": method--->" + num--);
  }

}
package com.gc.thread;

public class Demo {
  public static void main(String[] args) {
   
    SynchronizdMethod runnable = new SynchronizdMethod();
   
    //传入同一个Runnable接口子类对象,让多线程操作Runnable中封装的共享资源
    Thread a = new Thread(runnable);
    Thread b = new Thread(runnable);
   
    //开启线程  【注意:一个线程只能调用1次start(),多次调用将抛"线程运行状态异常"】
    a.start();
    //让主线程睡眠一小会,让a线程先执行,a线程将执行同步代码块中的代码
    try {
      Thread.sleep(10);//主线程睡眠的目的:让a线程先进入到同步代码块中,将标记改为false
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    //a线程改变flag标记之后,再开启b线程,让b线程执行同步函数中的代码
    b.start();
  }
}

评分

参与人数 1技术分 +1 收起 理由
黄晓鑫 + 1

查看全部评分

回复 使用道具 举报
当run方法中的代码都是多线程同步代码时 就用同步代码块 并且要保证该同步函数不是静态的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马