Java多线程之synchronized(转载)

以前有些疑问或是关注不到的,这里提供了一些参考。主要看文字部分,自己做实验

最基本的synchronized Method的使用

packagecom.jadyer.thread.sync;

/**
 * SynchronizedMethodTest
 *
 * @see===================================================================================================
 * @see概述:Java中的每个对象都有一个锁(lock)或者叫做监视器(monitor)
 * @see说明:当synchronized关键字修饰一个方法时,则该方法为同步方法
 * @see当某个线程访问某个对象的synchronized方法时,则表示将该对象上锁
 * @see此时其它的任何线程,均无法访问该对象中的任何一个synchronized方法(但允许访问该对象中的非synchronized方法)
 * @see直到该线程所访问的synchronized方法执行完毕(或者抛出了异常)之后,该对象的锁才会被释放
 * @see此时其它的任何线程,才被允许访问该synchronized方法,或者是该对象中的其它synchronized方法
 * @see===================================================================================================
 * @see总结:如果一个对象有多个synchronized方法,某一时刻某个线程已经执行了该对象中的某一个synchronized方法
 * @see那么在该方法没有执行完毕之前,其它线程是无法访问该对象中的,包括该方法在内的,任何一个synchronized方法
 * @see重点在于判断Synchronized锁的是谁。如果该方法是静态的,则锁Class对象,否则锁的就是当前对象
 * @see===================================================================================================
 * @see补充:1)这只是针对多个线程操作同一个类的同一个对象的情况。www.linuxidc.com若多个线程操作同一个类的不同对象,则不存在这种情况
 * @see2)Java中的volatile变量也可以看作是一种"程度较轻的synchronized"
 * @see关于volatile的更多信息,请参考http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
 * @see备注:实际项目中,用到的更多的还是JDK5.0开始推出的Java并发包,即java.util.concurrent包里面的工具类
 * @seejava.util.concurrent可以非常细粒度的实现并发。比如线程访问到了一个已被锁的对象,它可以让这个线程等到10秒
 * @see10秒后如果该对象仍未被解锁,那么就可以返回给用户超时的提示等,而如果使用synchronized则是无法这么精确控制的
 * @see===================================================================================================
 * @see注意:1)当synchronized方法执行完或者发生异常时,会自动释放锁
 * @see2)被synchronized保护的数据应该是private的,否则也就没必要去通过方法来访问这个public的数据了
 * @see===================================================================================================
 * @author宏宇
 * @createFeb21,20125:29:39PM
 */
public class SynchronizedTest {
    public static void main(String[] args) {
        Bank bank = new Bank();

        Thread tt11 = new Thread(new ThreadRMB(bank));

//new一个新的Bank对象。此时存在两个Bank对象,并且它们属于同一个类的不同的对象
//如要验证多个线程操作同一个类的不同的对象的synchronized方法,只需取消注释该行代码即可
//bank=newBank();

        Thread tt22 = new Thread(new ThreadDollar(bank));

        tt11.start();
        tt22.start();
    }
}


class ThreadRMB implements Runnable {
    private Bank bank;

    public ThreadRMB(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.getRMB();
    }
}


class ThreadDollar implements Runnable {
    private Bank bank;

    public ThreadDollar(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.getDollar();
    }
}


class Bank {
    public synchronized void getRMB() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

    public synchronized void getDollar() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
} 

下面演示的是synchronized static Method的使用

packagecom.jadyer.thread.sync;

/**
 * SynchronizedStaticMethodTest
 *
 * @see说明:如果某个synchronized方法是static的
 * @see那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是该方法所在的对象所对应的Class对象
 * @see因为Java中无论一个类有多少个对象,这些对象都会对应唯一的一个Class对象
 * @see因此当线程分别访问同一个类的两个对象的两个static的synchronized方法时,它们的执行顺序也是顺序执行的
 * @see即一个线程先执行一个static的synchronized方法,执行完毕后,另一个线程才开始执行另一个static的synchronized方法
 * @see总结:重点在于判断synchronized锁的是谁。www.linuxidc.com如果该方法是静态的,则锁Class对象,否则锁的就是当前对象
 * @author宏宇
 * @createFeb21,20125:29:39PM
 */
public class SynchronizedStaticTest {
    public static void main(String[] args) {
        Bank bank = new Bank();

        Thread tt11 = new Thread(new ThreadRMB(bank));
        Thread tt22 = new Thread(new ThreadDollar(bank));

        tt11.start();
        tt22.start();
    }
}


class ThreadRMB implements Runnable {
    private Bank bank;

    public ThreadRMB(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.getRMB();
    }
}


class ThreadDollar implements Runnable {
    private Bank bank;

    public ThreadDollar(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.getDollar();
    }
}


class Bank {
    //如要验证synchronized锁同一个类的对象,和锁它的Class对象的区别
//可去掉static关键字,再查看控制台打印,即publicsynchronizedvoidgetRMB()
    public synchronized static void getRMB() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

    public synchronized static void getDollar() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep((long) (Math.random() * 1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

最后演示的是synchronized Block的使用

packagecom.jadyer.thread.sync;

/**
 * SynchronizedBlockTest
 *
 * @author宏宇
 * @createFeb21,20125:29:39PM
 */
public class Synchronized BlockTest {
    public static void main(String[] args) {
        Bank bank = new Bank();

        Thread tt11 = new Thread(new ThreadRMB(bank));

//如果要验证synchronized(this)锁的是当前类的对象,而非当前类的Class对象
//则可取消注释该行代码,再观察控制台打印效果。效果应该是两个线程并发执行的输出
//bank=newBank();

        Thread tt22 = new Thread(new ThreadDollar(bank));

        tt11.start();
        tt22.start();
    }
}


class ThreadRMB implements Runnable {
    private Bank bank;

    public ThreadRMB(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.getRMB();
    }
}


class ThreadDollar implements Runnable {
    private Bank bank;

    public ThreadDollar(Bank bank) {
        this.bank = bank;
    }

    @Override
    public void run() {
        bank.getDollar();
    }
}


/**
 * Bank
 *
 * @see说明:synchronized块的写法:synchronized(object){//TODO...},它表示线程在执行的时候,会对object对象上锁
 * @see通常会把java.lang.Object对象传进来,事实上这里可以传进来任何的对象
 * @see因为它是一个没有实际作用的对象,其仅仅起到锁的作用,就像一个标识一样
 * @see作用:它表示,如果线程能够进入到这里,即执行到这里,那么,就将object对象锁上
 * @see如果另一个线程也执行到这里,发现object对象已上锁,则会等待其解锁后,才会去执行synchronized块里面的代码
 * @see补充:synchronized(this)表示对当前类的对象上锁。注意,它锁的不是当前类的Class对象
 * @seesynchronized(Bank.class)表示对当前类的Class对象上锁
 * @author宏宇
 * @createFeb22,20122:29:16AM
 */
class Bank {
    private Object bj11 = new Object();
    private Object obj22 = new Object();

    public void getRMB() {
//synchronized(obj11){
        synchronized (Bank.class) {
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }

    public void getDollar() {
//synchronized(obj11){
//synchronized(obj22){
        synchronized (this) {
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值