zoukankan      html  css  js  c++  java
  • 线程的同步

    1. 线程同步是对不同线程的协调。

    2. 线程之间的四种关系(1)不相关的线程。(2)相关但无需同步的线程。(3)互斥线程。(4)相互通信式互斥线程。

    3. 不相关的线程。用以执行不同功能的线程之间没有任何交互关系。

    4. 相关但无需同步的线程。可用于分解处理任务。采用一组线程,使之分别作用于同一数据结构的不同数据部分,线程之间没有交互关系。eg1. 为每个套接字连接请求创建一个新的线程。eg2. 守护线程。

    5. 守护线程。demon或daemon。守护线程以后台方式运行,用于为其他程序或线程提供服务。

    // 设定为守护线程
    myThread.setDemon(true);

    Java程序不会停止守护线程。eg. 维护打印机队列的线程。

    6. 启动多个相同的线程,为解决同一问题而分别处理不同的数据部分。

    7. 测试一个给定的数值是否为素数。把给定的数值分成不同的数值段,从而确定线程的数量,由每个线程分别测算划定数值段内的每一个数值。

    质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。

    class TestRange extends Thread{
        static long possPrime;
        long from, to;
    
        TestRange(int from, long possPrime){
            this.possPrime = possPrime;
            this.from = (from == 0) ? 2 : from;
            this.to = from + 99;
        }
    
        public void run(){
            for(long i = from; i <= to && i < possPrime; i++){
                if(possPrime % i == 0){
                    break;
                }
                yield();
            }
        }
    }

    8. 在Java API中,Thread类中有三个方法已被停用:(1)挂起suspend(); (2)恢复resume(); (3)停止stop();

    9. 线程的停止。应当采用编码方式的实现,即通过修改某一变量,通知目标线程停止运行。目标线程应该定期查看这个变量。

    10. 如果想要停止因I/O问题而挂起或处于封锁状态的线程,可通过调用interrupt()方法,向线程发送一个异常信息。

    11. 互斥线程。在一定的时间内,线程需要采用互斥方式运行。当线程需要操作同一数据结构中的同一数据部分时,这些线程必须相互等待以免同时修改同一数据,造成数据结果的不确定性。这些线程就是互斥线程。

    12. join()方法。主线程将使用线程的join()方法等待每个线程的完成。

    public class P
    {
        // 气压表的当前读数
        static int pressureGauge = 0;
        // 气压安全范围上线
        static final int safetyLimit = 20;
        
        public static void main(String[] args)
        {
            Pressure[] p1 = new Pressure[10];
            for(int i = 0; i < 10; i++)
            {
                p1[i] = new Pressure();
                p1[i].start();
            }
            // 等待线程结束
            for(int i = 0; i < 10; i++)
            {
                try
                {
                    p1[i].join();
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
            System.out.println("气压表当前读数是:" + pressureGauge + "\n气压安全范围上线:" + safetyLimit);
        }
        
        static class Pressure extends Thread
        {
            void raisePressure()
            {
                if(P.pressureGauge < P.safetyLimit - 15)
                {
                    try
                    {
                        sleep(100);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    P.pressureGauge += 15;
                }
            }
            public void run()
            {
                raisePressure();
            }
        }
    }

     13. 当两个或多个线程同时更新同一个数值时,竞争条件(数据竞争)就会出现。在通常的数据竞争情况下,最困难的问题是无法调试。这是不可重复的问题,我们无法预知数据何时会出现不一致的情况。

    14. 线程同步的解决方案。用以确保并发情况下数据的完整性。

    (1)测试和设置指令。所有的通用CPU都具有这种指令。指令本身不提供封锁功能,但可以基于这种指令实现高级的同步控制机制。

    (2)PV信号灯。信号灯一直是一种主要的同步原语。信号灯可以进行加减计数:P意味着减1操作,V意味着加1操作。利用测试和设置指令很容易实现信号灯控制原理。信号灯是一种底层的控制机制,程序员很难读取和调试,但可以使用信号灯实现高级的控制机制。

    (3)读写锁(互斥锁)。提供一种简单的同步控制机制。在任何给定的时刻,只有一个线程能够执行互斥锁保护的代码块。利用信号灯,很容易实现互斥锁。

    (4)监控器。是一种基于锁和变量的高级同步控制机制,其中的变量可用于跟踪某些相关的条件。利用读写锁,很容易实现监控器。监控器定义了若干方法,其中两个预定义的方法是wait()和notify()。

    15. 在采用何种同步技术方面,并没有一个通用的标准。

    16. 避免数据竞争。(1)无论两个线程何时访问同一个数据,必须采用互斥的方法进行处理。(2)在任意时刻允许两个线程同时读数据,但不允许有两个以上的线程对同一数据同时进行读写。(3)两个线程更不能同时写一个数据。

    17. 线程互斥。互斥是一种保持同步的协议,可以确保当一个线程访问某一特定的数据时,其他线程不会再操作同一数据。在Java中,线程的互斥是建立在对象数据基础之上的。系统中的任何对象都可以用做线程的同步控制。我们可以显式地使用synchronized关键字,或隐式地提供一个用于同步的对象。运行时系统将负责控制并提供必要的代码,确保在一个给定的时刻最多只有一个线程能够锁住特定的对象。

    18. synchronized(同步的)关键字。可用于(1)类方法(2)实例方法(3)代码块。在每一种情况下,都必须获取一个指定对象的互斥锁,然后才能执行代码块,直到代码块执行结束后才释放锁。

    19. 程序员惟一需要做的是:指定需要互斥执行的代码区和对象。在指定互斥执行的代码区时要尽可能地小一些,因为互斥执行会影响系统的性能。

    20. 使用synchronized关键字。同步代码块。如果可能的话,最好使用正被更新的对象作为同步锁。

    在这个例子中,被更新的变量是整数类型,都不是对象类型,所以借用Object对象。只有获取对象o的互斥锁,才可以执行指定的代码区。

    public class P
    {
        // 气压表的当前读数
        static int pressureGauge = 0;
        // 气压安全范围上线
        static final int safetyLimit = 20;
        
        static Object o = new Object();
        
        public static void main(String[] args)
        {
            Pressure[] p1 = new Pressure[10];
            for(int i = 0; i < 10; i++)
            {
                p1[i] = new Pressure();
                p1[i].start();
            }
            // 等待线程结束
            for(int i = 0; i < 10; i++)
            {
                try
                {
                    p1[i].join();
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
            System.out.println("气压表当前读数是:" + pressureGauge + "\n气压安全范围上线:" + safetyLimit);
        }
        
        static class Pressure extends Thread
        {
            void raisePressure()
            {
                if(P.pressureGauge < P.safetyLimit - 15)
                {
                    try
                    {
                        sleep(100);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    P.pressureGauge += 15;
                }
            }
            public void run()
            {
                synchronized (o)
                {
                    raisePressure();
                }
            }
        }
    }

    21. 同步类方法。在这种情况下,提供互斥锁的对象是隐式的。

    把一个static修饰的方法指定为同步的(synchronized),在任何给定的时间里,只有一个类对象可以执行static synchronized修饰的方法。

    static class Pressure extends Thread
    {
        static synchronized void raisePressure()
        {
            if(P.pressureGauge < P.safetyLimit - 15)
            {
                try
                {
                    sleep(100);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                P.pressureGauge += 15;
            }
        }
        public void run()
        {
            raisePressure();
        }
    }

    22. 同步实例方法。在这种情况下,提供互斥锁的对象是隐式的,也就是方法调用对应的this对象。

    为了把一个实例的方法定义为互斥的,可以把关键字synchronized加到实例方法的前面。

     

     

  • 相关阅读:
    多IDC数据分布--MySQL多机房部署
    Mongodb~连接串的整理
    Jenkins~配合Docker及dotnetCore进行生产和测试环境的灵活部署
    jenkins~集群分发功能的具体实现
    DotNetCore跨平台~linux上还原自主nuget包需要注意的问题
    jenkins~集群分发功能和职责处理
    HDU 2074 叠筐
    破解Veeam过程
    hdu1015(Safecracker )
    Oracle—RMAN备份(一)
  • 原文地址:https://www.cnblogs.com/fengzhblog/p/2775084.html
Copyright © 2011-2022 走看看