java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 
    将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 
    从而保证了该变量的唯一性和准确性。
 
 
 
1.同步方法 
    即有synchronized关键字修饰的方法。 
    由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 
    内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
 
 
    代码如: 
    public synchronized void save(){}
 
 
   注: synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类
 
 
 
2.同步代码块 
    即有synchronized关键字修饰的语句块。 
    被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
 
 
    代码如: 
    synchronized(object){ 
    }
 
 
    注:同步是一种高开销的操作,因此应该尽量减少同步的内容。 
    通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。 
     
    代码实例: 
    
 
复制代码
package com.xhj.thread;
 
    /**
     * 线程同步的运用
     * 
     * @author XIEHEJUN
     * 
     */
    public class SynchronizedThread {
 
        class Bank {
 
            private int account = 100;
 
            public int getAccount() {
                return account;
            }
 
            /**
             * 用同步方法实现
             * 
             * @param money
             */
            public synchronized void save(int money) {
                account += money;
            }
 
            /**
             * 用同步代码块实现
             * 
             * @param money
             */
            public void save1(int money) {
                synchronized (this) {
                    account += money;
                }
            }
        }
 
        class NewThread implements Runnable {
            private Bank bank;
 
            public NewThread(Bank bank) {
                this.bank = bank;
            }
 
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    // bank.save1(10);
                    bank.save(10);
                    System.out.println(i + "账户余额为:" + bank.getAccount());
                }
            }
 
        }
 
        /**
         * 建立线程,调用内部类
         */
        public void useThread() {
            Bank bank = new Bank();
            NewThread new_thread = new NewThread(bank);
            System.out.println("线程1");
            Thread thread1 = new Thread(new_thread);
            thread1.start();
            System.out.println("线程2");
            Thread thread2 = new Thread(new_thread);
            thread2.start();
        }
 
        public static void main(String[] args) {
            SynchronizedThread st = new SynchronizedThread();
            st.useThread();
        }
 
    }
复制代码
     
3.使用特殊域变量(volatile)实现线程同步
 
    a.volatile关键字为域变量的访问提供了一种免锁机制, 
    b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新, 
    c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 
    d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量 
    
    例如: 
        在上面的例子当中,只需在account前面加上volatile修饰,即可实现线程同步。 
    
    代码实例: 
    
 
复制代码
      //只给出要修改的代码,其余代码与上同
        class Bank {
            //需要同步的变量加上volatile
            private volatile int account = 100;
 
            public int getAccount() {
                return account;
            }
            //这里不再需要synchronized 
            public void save(int money) {
                account += money;
            }
        }
复制代码
 
    注:多线程中的非同步问题主要出现在对域的读写上,如果让域自身避免这个问题,则就不需要修改操作该域的方法。 
    用final域,有锁保护的域和volatile域可以避免非同步的问题。 
    
4.使用重入锁实现线程同步
 
    在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。 
    ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 
    它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力
 
 
    ReenreantLock类的常用方法有:
 
        ReentrantLock() : 创建一个ReentrantLock实例 
        lock() : 获得锁 
        unlock() : 释放锁 
    注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用 
        
    例如: 
        在上面例子的基础上,改写后的代码为: 
        
    代码实例: 
    
 
复制代码
//只给出要修改的代码,其余代码与上同
        class Bank {
            
            private int account = 100;
            //需要声明这个锁
            private Lock lock = new ReentrantLock();
            public int getAccount() {
                return account;
            }
            //这里不再需要synchronized 
            public void save(int money) {
                lock.lock();
                try{
                    account += money;
                }finally{
                    lock.unlock();
                }
                
            }
        }
复制代码
          
    注:关于Lock对象和synchronized关键字的选择: 
        a.最好两个都不用,使用一种java.util.concurrent包提供的机制, 
            能够帮助用户处理所有与锁相关的代码。 
        b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码 
        c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁 
        
5.使用局部变量实现线程同步 
    如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 
    副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
 
 
 
    ThreadLocal 类的常用方法
 
 
 
    ThreadLocal() : 创建一个线程本地变量 
    get() : 返回此线程局部变量的当前线程副本中的值 
    initialValue() : 返回此线程局部变量的当前线程的"初始值" 
    set(T value) : 将此线程局部变量的当前线程副本中的值设置为value
 
 
 
    例如: 
        在上面例子基础上,修改后的代码为: 
        
    代码实例: 
        
 
复制代码
//只改Bank类,其余代码与上同
        public class Bank{
            //使用ThreadLocal类管理共享变量account
            private static ThreadLocal<Integer> account = new ThreadLocal<Integer>(){
                @Override
                protected Integer initialValue(){
                    return 100;
                }
            };
            public void save(int money){
                account.set(account.get()+money);
            }
            public int getAccount(){
                return account.get();
            }
        }
复制代码
    注:ThreadLocal与同步机制 
        a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。 
        b.前者采用以"空间换时间"的方法,后者采用以"时间换空间"的方式
 
转自:http://www.2cto.com/kf/201408/324061.html

Java线程同步的方式的更多相关文章

  1. Java线程同步的四种方式详解(建议收藏)

    ​ Java线程同步属于Java多线程与并发编程的核心点,需要重点掌握,下面我就来详解Java线程同步的4种主要的实现方式@mikechen 目录 什么是线程同步 线程同步的几种方式 1.使用sync ...

  2. Java线程同步之一--AQS

    Java线程同步之一--AQS 线程同步是指两个并发执行的线程在同一时间不同时执行某一部分的程序.同步问题在生活中也很常见,就比如在麦当劳点餐,假设只有一个服务员能够提供点餐服务.每个服务员在同一时刻 ...

  3. (删)Java线程同步实现一:synchronzied和wait()/notify()

    上面文章(2.Java多线程总结系列:Java的线程控制实现)讲到了如何对线程进行控制,其中有一个是线程同步问题.下面我们先来看一个例子: 1.一个典型的Java线程安全例子 package com. ...

  4. java 线程同步 原理 sleep和wait区别

    java线程同步的原理java会为每个Object对象分配一个monitor, 当某个对象(实例)的同步方法(synchronized methods)被多个线程调用时,该对象的monitor将负责处 ...

  5. Java线程同步_1

    Java线程同步_1 synchronized 该同步机制的的核心是同步监视器,任何对象都可以作为同步监视器,代码执行结束,或者程序调用了同步监视器的wait方法会导致释放同步监视器 synchron ...

  6. java线程 同步临界区:thinking in java4 21.3.5

    java线程 同步临界区:thinking in java4 21.3.5 thinking in java 4免费下载:http://download.csdn.net/detail/liangru ...

  7. JAVA - 线程同步和线程调度的相关方法

    JAVA - 线程同步和线程调度的相关方法 wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁:wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等 ...

  8. java线程同步实的现方式

    为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他 ...

  9. Java线程同步和线程通信

    一.线程同步 当多个线程访问同一个数据时,非常容易出现线程安全问题.这时候就需要用线程同步. 不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全. 1.同步 ...

随机推荐

  1. 关于 三星 I9100 (水货)

    前天陪好友去买水货9100,总结了一点经验,觉得挺有用的,今天整理一下写出来...有 需要的可以看看..原创整理.. 一,当然是检查外观(检查USB接口有没有磨损,检查摄像头是否有灰尘,检查屏幕是不是 ...

  2. UVaLive 6698 Sightseeing Bus Drivers (水题,贪心)

    题意:n个工人,有n件工作a,n件工作b,每个工人干一件a和一件b,a[i] ,b[i]代表工作时间,如果a[i]+b[j]>t,则老板要额外付钱a[i]+b[j]-t;现在要求老板付钱最少: ...

  3. VM VirtualBox 上安装 CentOs6.4(详细)

    在网上下载:CentOS-6.4-i386-bin-DVD1.iso镜像. 这是我在VBox上安装CentOs6.4的过程: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12 ...

  4. linux 下查看文件个数及大小

    ls -l |grep "^-"|wc -l   或      find ./company -type f | wc -l 查看某文件夹下文件的个数,包括子文件夹里的. ls - ...

  5. android 三种弹出框之一PopupWindow

    PopupWindow 在android的弹出框我目前了解到的是有三种:AlertDialog,PopupWindow,Activity伪弹框, AlertDialog太熟悉了,这里就不介绍了 就先看 ...

  6. C:指针

    指针 指针数组   参考1   参考2  参考3  参考4 1.指针 也是一种变量.指针内部存的是一块内存的地址. //指针: 通常我们说的指针其实是指针变量,相比于其他基本数据类型的变量不同,它存储 ...

  7. Oracle闪回

    在PLSQL开发时,有时候会遇到对表的误删除,其实遇到这种情况不需要紧张,如果问题较大,请DBA帮忙,如果只是小问题,只需自己处理,利用flashback闪回操作即可,可将表进行恢复 在删除表时,系统 ...

  8. chrome 41 空格 &nbsp;

    chrome 41对半角空格的解析 当做一个汉字宽度来处理了. 导致很多网站出现异常. 目前能想到的方法是删掉用来规范格式的空格. 老版chrome chrome41 和讯网也有这种问题 有更好的处理 ...

  9. javaScript-原型、继承-02

    原型链 首先回顾下实列.构造函数.原型对象之间的关系: 实列都包含指向原型对象的一个指针(_proto_): 构造函数都有prototype(原型属性)指向原型对象的指针: 原型是一个对象也存在一个内 ...

  10. Winform XiaoCai.WinformUI 框架界面设计

    开源用户界面和布局的套件XiaoCai.WinformUI(美化用户界面利器) http://www.cnblogs.com/aganqin/p/3400453.html 源码下载:https://g ...