多线程并发中的同步

多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。参考自http://www.cnblogs.com/phinecos/archive/2010/03/13/1684877.html

实例说明:1.貌似同步,实际不同步的情况

package com.thread.code.sync;

/**
 * 不能实现线程同步的例子
 * @author  魅力_小生
 * @version  [版本号, 2016年3月4日]
 */
public class CannotSync
{
    public static void main(String[] args)
    {
        CannotSync test = new CannotSync();
        //定义5个线程,希望不打断输出:线程1--1..5;线程2--1..5;...线程5--1..5;
        for (int i = 0; i < 5; i++)
        {
            new Thread(test.new MyThread(),"线程"+i).start();
        }
        //结果发现:打印结果并没有按顺序输出
        /*
         * 原因:在普通方法前面加synchronized,锁住的是当前的this对象,也就是每个个new MyThread()对象;
         *      代码中创建了10个线程,而每个线程都持有this对象的对象锁,这不能实现线程的同步
         */
    }

    class MyThread implements Runnable{
        @Override
        //貌似同步,实际不同步(当只有一个线程调用时同步,多线程时不同步)
        public synchronized void run()
        {
            for (int i = 0; i < 10; i++)
            {
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
        }
    }
}

打印结果:线程1未执行完,线程3打断,接着线程4又打断3,接着线程2又打断4...

线程1--0
线程1--1
线程1--2
线程1--3
线程1--4
线程1--5
线程3--0
线程4--0
线程2--0
线程2--1
线程2--2
线程2--3
线程2--4
线程2--5
线程0--0
...


下面看看能实现同步的几种情况:

1.同步锁指向同一个对象(外部定义的对象)

package com.thread.code.sync;

/**
 * 实现线程同步的例子1:同步锁指向同一个对象(外部定义的对象)
 * @author  魅力_小生
 * @version  [版本号, 2016年3月4日]
 */
public class Sync1
{
    public static void main(String[] args)
    {
        Sync1 test = new Sync1();

        //定义一个共用obj,用于共享资源的锁指向同一个对象,实现同步
        Object obj = new Object();
        //定义5个线程,共同竞争同步代码块,先竞争到的先执行完同步块,中间不会被打断
        for (int i = 0; i < 5; i++)
        {
            new Thread(test.new MyThread(obj),"线程"+i).start();
        }
    }

    class MyThread implements Runnable{
        private Object obj;
        public MyThread(Object obj){
            this.obj = obj;
        }
        @Override
        public void run()
        {
            synchronized(obj){
                for (int i = 0; i < 10; i++)
                {
                    System.out.println(Thread.currentThread().getName()+"--"+i);
                }
                System.out.println("------------");
            }
        }
    }
}

2.同步锁指向同一个对象(内部定义静态对象)

package com.thread.code.sync;

/**
 * 实现线程同步的例子2:同步锁指向同一个对象(内部定义静态对象)
 * @author  魅力_小生
 * @version  [版本号, 2016年3月4日]
 */
public class Sync2
{
    public static void main(String[] args)
    {
        //定义5个线程,共同竞争同步代码块,先竞争到的先执行完同步块,中间不会被打断
        for (int i = 0; i < 5; i++)
        {
            new Thread(new MyThread(),"线程"+i).start();
        }
    }

    static class MyThread implements Runnable{
        //定义静态对象,用于共享资源的锁指向同一个对象,实现同步
        private static Object obj = new Object();
        @Override
        public void run()
        {
            synchronized(obj){
                for (int i = 0; i < 10; i++)
                {
                    System.out.println(Thread.currentThread().getName()+"--"+i);
                }
                System.out.println("------------");
            }
        }
    }
}

3.使用静态同步方法,而不是普通同步方法

package com.thread.code.sync;

/**
 * 实现线程同步的例子3:使用静态同步方法,而不是普通同步方法
 * @author  魅力_小生
 * @version  [版本号, 2016年3月4日]
 */
public class Sync3
{
    public static void main(String[] args)
    {
        //定义5个线程,希望不打断输出:线程1--1..5;线程2--1..5;...线程5--1..5;
        for (int i = 0; i < 5; i++)
        {
            new Thread(new MyThread(),"线程"+i).start();
        }
    }

    static class MyThread implements Runnable{
        @Override
        public void run()
        {
            print();
        }
        /*
         * 静态同步方法:
         *  静态方法是所有类实例对象所共享的,因此线程对象在访问此静态方法时是互斥访问的,从而可以实现线程的同步
         */
        private static synchronized void print()
        {
            for (int i = 0; i < 10; i++)
            {
                System.out.println(Thread.currentThread().getName()+"--"+i);
            }
            System.out.println("------------");
        }
    }
}

上面这些同步情况的打印结果:线程竞争到资源后,未被打断

线程0--0
线程0--1
线程0--2
线程0--3
线程0--4
线程0--5
线程0--6
线程0--7
线程0--8
线程0--9
------------
线程3--0
线程3--1
线程3--2
线程3--3
线程3--4
线程3--5
线程3--6
线程3--7
线程3--8
线程3--9
------------
线程4--0
线程4--1
线程4--2
线程4--3
线程4--4
线程4--5
线程4--6
线程4--7
线程4--8
线程4--9
------------
线程2--0
线程2--1
线程2--2
线程2--3
线程2--4
线程2--5
线程2--6
线程2--7
线程2--8
线程2--9
------------
线程1--0
线程1--1
线程1--2
线程1--3
线程1--4
线程1--5
线程1--6
线程1--7
线程1--8
线程1--9
------------
时间: 2024-10-13 22:19:28

多线程并发中的同步的相关文章

Java多线程并发中 CAS 的使用与理解

一.CAS (Compare And Swap): CAS(Compare And Swap),即比较并交换 CAS(V,E,N).是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——要更新的变量(V).预期原值(E)和新值(N).核心算法是如果V 值等于E 值,则将V 的值设为N .若V 值和E 值不同,则说明已经有其他线程做了更新,则当前线程不做更新,直到V.E两个值相等,才更新V的值. 1.代码演示: /* * 原子变量类: * AtomicBoolean *

Cocos2d-x优化中多线程并发访问

多线程并发访问在Cocos2d-x引擎中用的不是很多,这主要是因为中整个结构设计没有采用多线程.源自于Objective-C的Ref对象,需要使用AutoreleasePool进行内存管理,AutoreleasePool是非线程安全的,所有不推荐在子多线程中调用Ref对象的retain(). release()和autorelease()等函数.另外,OpenGL上下文对象也是不支持线程安全的.但是有的时候我们需要异步加载一些资源,例如:加载图片纹理.声音的预处理和网络请求数据等.如果是异步加载

多线程爬坑之路--并发,并行,synchonrized同步的用法

一.多线程的并发与并行: 并发:多个线程同时都处在运行中的状态.线程之间相互干扰,存在竞争,(CPU,缓冲区),每个线程轮流使用CPU,当一个线程占有CPU时,其他线程处于挂起状态,各线程断续推进. 并行:多个线程同时执行,但是每个线程各自有自己的CPU,不存在CPU资源的竞争,他们之间也可能存在资源的竞争. 并发发生在同一段时间间隔内,并行发生在同一时刻内.并发执行的总时间是每个任务的时间和,而并行则取决于最长任务的时间. 下面看一下A,B两个任务在并行和并发情况下是怎么执行的:[不考虑其他资

进程 线程 多线程 并发 同步异步

进程 线程 多线程 并发 同步异步 很多人对进程,线程,多线程,并发,同步,异步等概念感到困惑,这都是大学没好好听课的缘故啊.咱在这里帮感到概念给感到困惑的同学复习下. 程序 程序用来描述计算机所完成的独立功能,并在时间上严格地按前后次序相继地进行计算机操作序列集合,是一个静态概念. 进程 并发执行的程序在执行过程中分配和管理资源的基本单位.是一个动态的执行过程. 进程的静态描述 进程控制块PCB 有关程序段 该程序员对齐进行操作的数据结构集 进程控制块PCB 进程控制块PCB是系统管制进程存在

C#使用读写锁解决多线程并发写入文件时线程同步的问题

读写锁是以 ReaderWriterLockSlim 对象作为锁管理资源的,不同的 ReaderWriterLockSlim 对象中锁定同一个文件也会被视为不同的锁进行管理,这种差异可能会再次导致文件的并发写入问题,所以 ReaderWriterLockSlim 应尽量定义为只读的静态对象. 多线程同时写入文件 class Program { static int writeCount = 0; static int wrongCount = 0; static void Main(string

Java并发编程(8):多线程环境中安全使用集合API(含代码)

Java并发编程(8):多线程环境中安全使用集合API(含代码)JAVA大数据中高级架构 2018-11-09 14:44:47在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对象锁便是一种浪费,另外在不必要的时候如果滥用同步化,也有可能会带来死锁.因此,对于更改集合内容的方法,没有一个是同步化的.集合本质上是非多线程安全的,当多个线程与集合交互时

简单的多线程并发同步演示

#include "stdafx.h"#include <iostream>#include <Windows.h>using namespace std;HANDLE hMutex;DWORD WINAPI Fun(LPVOID lp){    while(1){        WaitForSingleObject(hMutex,INFINITE);        cout<<"fun"<<endl;//如果不用信

JAVA并发七(多线程环境中安全使用集合API)

在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对象锁便是一种浪费,另外在不必要的时候如果滥用同步化,也有可能会带来死锁.因此,对于更改集合内容的方法,没有一个是同步化的.集合本质上是非多线程安全的,当多个线程与集合交互时,为了使它多线程安全,必须采取额外的措施. 在Collections类 中有多个静态方法,它们可以获取通过同步方法封装非同步集合

【Java并发编程】之八:多线程环境中安全使用集合API(含代码)

 在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于Vector来说,用来添加和删除元素的方法是同步的.如果只有一个线程与Vector的实例交互,那么,要求获取和释放对象锁便是一种浪费,另外在不必要的时候如果滥用同步化,也有可能会带来死锁.因此,对于更改集合内容的方法,没有一个是同步化的.集合本质上是非多线程安全的,当多个线程与集合交互时,为了使它多线程安全,必须采取额外的措施. 在Collections类 中有多个静态方法,它们可以获取通过同步方法封装非同步集