Java 线程同步

Java 线程同步根本上是要符合一个逻辑:加锁------>修改------>释放锁

1、同步代码块

示例如下:

public class SyncBlock {
    static class DataWrap {
        int i;
    }

    static class SyncBlockThread extends Thread {
        private DataWrap date;

        public SyncBlockThread(DataWrap dataWrap) {
            this.date = dataWrap;
        }

        @Override
        public void run() {

            for (int i = 0; i < 10; i++) {
                synchronized (date) {
                    date.i++;
                    try {
                        sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName() + " " + date.i);
                }
            }
        }
    }

    public static void main(String[] args) {
        //多线程实现变量i依次加一输出
        DataWrap dataWrap = new DataWrap();

        new SyncBlockThread(dataWrap).start();
        new SyncBlockThread(dataWrap).start();
        new SyncBlockThread(dataWrap).start();
    }

}

示例中希望按照顺序依次输出整数。

通常同步代码块是需要锁定的对象,一般是需要并发访问的共享资源,任何线程在修改指定资源之前都首先对该资源加锁,在加锁期间其它线程无法修改该资源。从而保证了线程的安全性。另外线程在调用sleep或者yield时并不会让出资源锁。

2、同步方法

public class SyncMethod {

    static class DataWrap{
        int i;

        public synchronized void valueGrow(){
            i++;

            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }

    static class SyncMethodThread extends Thread {
        DataWrap dataWrap;

        public SyncMethodThread(DataWrap dataWrap){
            this.dataWrap = dataWrap;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                dataWrap.valueGrow();
            }
        }
    }

    public static void main(String[] args) {
        //实现顺序增长并输出Datawrap中的i

        DataWrap dataWrap = new DataWrap();

        new SyncMethodThread(dataWrap).start();
        new SyncMethodThread(dataWrap).start();
        new SyncMethodThread(dataWrap).start();
    }

}

同步方法是使用synchronized关键字修饰的某个方法,同步方法锁定的就是该对象本身,所以当一个线程调用了某个对象的同步方法后,如有其它线程调用该对象的其它同步方法,也依然要等待释放该对象的锁,因为该对象已被锁定。

3、同步锁

通过定义同步锁对象实现同步,这种情况下,同步锁使用Lock对象充当。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SyncLock {

    static class DataWrap{
        Lock lock = new ReentrantLock();
        int i;

        public void valueGrow(){
            lock.lock();
            try {
                i++;

                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " " + i);
            } finally {
                lock.unlock();
            }

        }
    }

    static class SyncLockThread extends Thread {
        DataWrap dataWrap;

        public SyncLockThread(DataWrap dataWrap){
            this.dataWrap = dataWrap;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                dataWrap.valueGrow();
            }
        }
    }

    public static void main(String[] args) {
        //实现顺序增长并输出Datawrap中的i

        DataWrap dataWrap = new DataWrap();

        new SyncLockThread(dataWrap).start();
        new SyncLockThread(dataWrap).start();
        new SyncLockThread(dataWrap).start();
    }

}

使用锁对象实现线程同步会更灵活一些,某些锁还具有一些特定的功能,其中比较常用的ReadWriteLock读写锁,ReentrantLock可重入锁。

时间: 2024-10-02 01:40:49

Java 线程同步的相关文章

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

thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155 package org.rui.thread.critical; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.uti

Java 线程同步执行(顺序执行)

关于线程,有两种实现方法, 一种是通过继承Runnable接口,另外一种通过扩展Thread类,两者的具体差别,可参考我找的这篇文章 http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html .本主主要是讲 线程的同步执行问题.. 如果程序是通过扩展Thread类的,网上的资料说可以通过 join()函数实现,但本人亲测,此法无法通过.程序如下: public class test1 extends Thread { pu

Java线程同步(synchronized)——卖票问题

卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题. Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1,当某个线程执行了synchronized(object)语句后,object对象的标志位变为0状态,直到执行完整个synchronized语句中的代码块后,该对象的标志位又回到1状态. 当一个线程执行到synchronized(object)语句的时候,先检查object对象的标志位,如果为0状态,

(转) Java线程同步阻塞, sleep(), suspend(), resume(), yield(), wait(), notify()

为了解决对共享存储区的访问冲突,Java 引入了同步机制.但显然不够,因为在任意时刻所要求的资源不一定已经准备好了被访问,反过来,同一时刻准备好了的资源也可能不止一个. 为解决访问控制问题,Java 引入阻塞机制.阻塞指的是暂停一个Java线程同步的执行以等待某个条件发生(如某资源就绪). sleep():允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时 间,指定的时间一过,线程重新进入可执行状态.典型地,sleep() 被用在等待某个资源就绪的情

Java线程同步模型-生产者与消费者

Java生产者与消费者模型是经典Java线程同步模型,涉及使用同步锁控制生产者线程和消费者线程同步运行问题.同步对象是仓库资源,生产者线程生产向仓库中生产商品,消费者线程从仓库中消费商品,当生产者线程生产的商品达到仓库的90%时,生产者线程停止生产并通知消费者线程开始消费,当消费者线程消耗到仓库的10%时,消费者线程停止消费并通知生产者线程恢复生产,如此循环往复过程. 如下图解: T1时刻分析 T2时刻 T3时刻 T4时刻 上图的分析,T3同T1时刻相同场景,T2同T2时刻相同场景,程序如此循环

Java线程同步和并发第1部分

通过优锐课核心java学习笔记中,我们可以看到,码了很多专业的相关知识, 分享给大家参考学习.我们将分两部分介绍Java中的线程同步,以更好地理解Java的内存模型. 介绍 Java线程同步和并发是复杂应用程序各个设计阶段中讨论最多的主题. 线程,同步技术有很多方面,它们可以在应用程序中实现高并发性. 多年来,CPU(多核处理器,寄存器,高速缓存存储器和主内存(RAM))的发展已导致通常是开发人员往往忽略的某些领域-例如线程上下文,上下文切换,变量可见性,JVM内存 型号与CPU内存型号. 在本

【java并发】(2) Java线程同步:synchronized锁住的是代码还是对象

在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在方法上. 关键是,不要认为给方法或者代码段加上synchronized就万事大吉,看下面一段代码: class Sync { public synchronized void test() { System.out.println("test开始.."); try { Thread.sle

【总结】Java线程同步机制深刻阐述

原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize

Java线程同步与死锁、生产者消费者模式以及任务调度等

一.Thread类基本信息方法 package Threadinfo; public class MyThread implements Runnable{ private boolean flag = true; private int num = 0; @Override public void run() { while(flag) { System.out.println(Thread.currentThread().getName()+"-->"+num++); } }