请教高手们一个问题  
在Java中 用 synchronized 锁住同一个类中的两个方法A,B;
他的意思是 我用A时B也不能被用还是我用A时A不能用,用B时B不能用?

解决方案 »

  1.   

    这样说也不严谨,应该说A、B方法只能有一个对象访问,比如说A方法已经有对象访问了,那么A方法不能再被该对象访问,B方法也不能
    因为每个对象有一个对象锁,使用A方法的时候,拿了这个锁,所以可以执行,但是尝试再次调用A方法的时候,对象锁已经被拿走了,所以要等待A方法释放锁才能执行,同理,尝试调用B方法也不行,因为对象锁已经被拿走了,也要等A方法释放锁之后才能执行
      

  2.   

    如果我需要同时锁住两个方法呢? 比如我在调用set方法时不允许有人来调用get方法
      

  3.   

    当一个线程调用方法A时,那么该线程就获得了synchronized对象的锁,由于该对象锁住了A,B所以其他线程都不能进入A,B之中,,,
      

  4.   

    synchronized对象的锁,是为了让这个方法只能一个对象接一个对象来访问,不能同时有两个对象来访问。一个对象访问就获得了锁,只有等他用完了,他才会释放锁,<就比如大超市放物品的柜子一样>
      

  5.   

    我觉得你需要明白2个概念:
    (1)锁的对象是什么?按照你的意思,那么就是这个类的实例了,即非静态同步方法;那么方法A访问时,这个实例就加锁了,这个时候B不能访问了,因为如果可以访问,既不是意味着这个对象加料2次锁,方法B只能等A结束访问,对象锁释放了才能访问;
    (2)要注意你锁的对象是这个实例,如果在NEW一个实例,是可以访问A或者B的,因为你加锁的不是这个新实例。
    不知道你有没有明白我的意思,这个是就学习同步方法最重要的注意事项了。然后最后一点是你尽量用同步代码块替代同步方法,这样节省锁的范围,提高性能。
      

  6.   

      各位大神没明白小弟的意思,我的意思是两个线程持有同一个对象访问一个类里面的两个非静态方法,我对这我需要对这两个方法同时同步,但是我如果在这两个方法名前分别加一个synchronrized关键字的话并不能得到这样的效果,例如 我同步了A,B两个方法,有a,b两个线程持同一实例访问。当a执行A方法时,b不能获得锁因此等待,当a执行完A以后,假如b获得A方法锁,执行后a此时可能还未获得B方法的锁,而由b强了先,此时a再执行B方法时数据都被a改过了。我直接上代码吧:
       package edu.cuit.wlgcx;class Demo {
    private int i = 100; synchronized int setI(int y) {
      
    return i = i - y;

    } synchronized  int getI() {

    return i;

    }}public class SynchronrizedTest implements Runnable { private Demo demo = new Demo(); public static void main(String[] args) { SynchronrizedTest test1 = new SynchronrizedTest(); Thread thread1 = new Thread(test1, "线程1");
    Thread thread2 = new Thread(test1, "线程2");
    thread1.start();
    thread2.start(); } @Override
    public void run() {
    for (int i = 0; i < 5; i++) {
    try {
    Thread.sleep(1);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } this.setI(10);
    System.out.println(demo.getI() + Thread.currentThread().getName()); }
    } int setI(int y) {
    return demo.setI(y);
    }}  如果多次执行就会发现输出结果会不一样
      

  7.   

    这么跟你说,每个对象有一个锁,每个对象的Class对象也有一个锁synchronized 非static方法要获取对象的锁才能执行synchronized static方法要获取对象的Class对象的锁才能执行所以,同一个对象中多个非static方法都是synchronized的话,进入了一个方法且未退出之前,是不能再进入该对象的非static synchronized方法的
      

  8.   

      
        有木有这种情况,a执行完A后,已经释放了A的锁,还未获得B的锁,但是b线程获得了A的锁,当b释放A的锁时,a获得了B的锁,此时数据依然被a修改过了,这种问题怎么解决呢?
      

  9.   

    楼主的示例其实共享的资源是test1,你需要同步的是这个对象。 import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;class Demo {
    private int i = 100; int setI(int y) {
    System.out.println("减去" + y);
    return i = i - y;
    } int getI() {
    return i;
    }}public class SynchronrizedTest implements Runnable {
    Lock lock = new ReentrantLock();
    private Demo demo = new Demo(); public static void main(String[] args) { SynchronrizedTest test1 = new SynchronrizedTest(); Thread thread1 = new Thread(test1, "线程1");
    Thread thread2 = new Thread(test1, "线程2");
    thread1.start();
    thread2.start(); } public void run() {
    for (int i = 0; i < 5; i++) {
    try {
    Thread.sleep(1);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    lock.lock();
    System.out.println(Thread.currentThread().getName() + "操作之前: " + demo.getI());
    this.setI(10);
    System.out.println(Thread.currentThread().getName() + "操作之后: " + demo.getI());
    System.out.println();
    lock.unlock();
    }
    } int setI(int y) {
    return demo.setI(y);
    }}
      

  10.   

        多谢12楼大神,但是我觉得还是有点瑕疵,我希望在class Demo里面就做好同步的处理,而不是等别人调用我的时候自己做处理,该怎么做处理呢? 
      

  11.   


    LZ,那是因为你的setI和getI是独立的两个方法,不在同一个synchronized块里,所以他们之间的调用有时间上的间隙,这样,在这个间隙中其他线程先执行的话,就会导致setI和getI的结果不同步this.setI(10);
    //这里就是时间间隙
    System.out.println(demo.getI() + Thread.currentThread().getName());
    把这两句代码写到同一个synchronized块才能保证setI和getI之间的一致

    syncronized(this) { //其他线程会在这里等待
        //(当然,这样的前提是你的线程都是执行相同的这段代码,
        //否则,因为这里的this和demo的synchronized不是同一个对象,也不能保证setI和getI同步)
        this.setI(10);
        System.out.println(demo.getI() + Thread.currentThread().getName());
    }