线程同步详解

原创 2016年05月31日 16:59:13

线程同步方式有很多种,其中一种便是synchronized,下面先用一个例子来说一下它的两种应用场景:

package thread;

public class TestSync implements Runnable{
    Timer timer=new Timer();
    public static void main(String args[]){
        TestSync test=new TestSync();
        Thread t1=new Thread(test);
        Thread t2=new Thread(test);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        t2.start();
    }
    public void run(){
        timer.add(Thread.currentThread().getName());
    }
}
class Timer{
    private static int num=0;
    //public synchronized void add(String name){第二种方式处理
    public void add(String name){
        //synchronized (this) {第一种方式处理线程同步
            num++;
            try{
                Thread.sleep(1);
            }catch(InterruptedException e){

            }
            System.out.println(name+",你是第"+num+"个使用timer的线程");
        //}
    }
}

如果用debug模式下慢点儿调试,输出结果是:
t1,你是第1个使用timer的线程
t2,你是第2个使用timer的线程

如果用start模式下慢点儿调试,输出结果是:
t2,你是第2个使用timer的线程
t1,你是第2个使用timer的线程

package thread;

public class TestDeadLock implements Runnable{//第三步
    public int flag=1;//第二步
    static Object o1=new Object(),o2=new Object();
    public void run(){
        System.out.println("flag="+flag);
        if(flag==1){
            synchronized (o1) {
                try{
                    Thread.sleep(500);
                }catch(Exception e){
                    e.printStackTrace();
                }
                synchronized (o2) {
                    System.out.println("1");
                }
            }
        }
        if(flag==0){
            synchronized (o2) {
                try{
                    Thread.sleep(500);
                }catch(Exception e){
                    e.printStackTrace();
                }
                synchronized (o1) {
                    System.out.println("0");
                }
            }
        }
    }
    public static void main(String args[]){
        TestDeadLock td1=new TestDeadLock();//第一步
        TestDeadLock td2=new TestDeadLock();
        td1.flag=1;
        td2.flag=0;
        Thread t1=new Thread(td1);
        Thread t2=new Thread(td2);
        t1.start();
        t2.start();
    }
}

在实践的过程中突然想到一个问题:
线程执行快慢与它的启动顺序有关吗?
后来在反复验证后发现,他们并没有直接关系。

上面的情况在很多情况下还是容易引起线程死锁的,像下图这样,一直在等待对方释放:
这里写图片描述
可以通过加大锁的粒度来减少死锁的情况。

这里写图片描述
像上图这样,加了同步效率降低,不同步数据不一致
不允许朵儿线程同时改,但允许多个线程同时读
这里写图片描述
打印结果:2000
为什么??
这里写图片描述

注意:如果两个方法改了同一个值,两个方法都应该加同步

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

线程同步详解

下面是本人在网上找到的关于线程同步的一篇好文章,比较经典,通熟易懂,转过来给大家分享一下。 我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程(Thread)。 ...
  • tjcyjd
  • tjcyjd
  • 2011-10-18 11:36
  • 1894

《VC++深入详解》学习笔记 第十六章 线程同步与异步套接字编程

1.事件对象 (1)事件对象也属于内核对象,它包含以下三个成员           1.使用计数          2.用于指明该事件...

剑指Offer——线程同步volatile与synchronized详解

(转)Java面试——线程同步volatile与synchronized详解注:本文转载地址 http://blog.csdn.net/seu_calvin/article/details/52370...

VC++深入详解笔记——16.线程同步与异步套接字

1.       事件对象 事件对象同上一课中的互斥对象一样属于内核对象,它包含三个成员:使用读数,用于指明该事件是一个自动重置的还是人工重置的事件的布尔值,用于指明该事件处于已通知状态还是未通知状...

《VC++深入详解》学习笔记[13]——第16章 线程同步与异步套接字编程

第16章 线程同步与异步套接字编程 1.事件对象        事件对象与互斥对象一样也属于内核对象。事件对象有两种不同的类型:        ①人工重置的事件对象:当人工重...

孙鑫 VC++深入详解第16课——线程同步与异步套接字编程

1.通过事件对象实现同步 ①创建事件对象CreateEvent ②设置为激活常态SetEvent ③等待信号量WaitForSingleObject ④关闭事件句柄CloseHandle 代码: #i...

线程同步(4):linux各种锁详解

在linux内核中,有很多同步机制。比较经典的有原子操作、spin_lock(忙等待的锁)、mutex(互斥锁)、semaphore(信号量)等。并且它们几乎都有对应的rw_XXX(读写锁),以便在能...

线程同步(3):内存模型及内存屏障详解

为了提升性能,CPU会乱序执行指令。内存屏障可以确保指令按照正确的顺序执行。RedHat的David Howells和IBM的Paul E. McKenney介绍了Linux内核的内存屏障设计。这里和...

线程同步的实现

  • 2017-08-25 16:27
  • 964B
  • 下载

线程同步编程实例

  • 2012-04-13 10:32
  • 1.14MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)