线程同步的方式、同步和互斥

线程同步的互斥的区别

  • 互斥是指线程的共享资源同时只允许一个访问者对它进行访问,具有独占性,但无法限制访问的顺序,也就是访问是无序的。
  • 同步是指在互斥的基础上,通过xx机制实现访问者对资源的有序访问,也就是说线程通过同步建立了执行顺序的关系。

线程同步的方式

  1. 信号量:它允许多个线程在同一时刻访问同一资源,但会限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore() 函数创建信号量时,要同时指出允许的最大资源数和当前可用资源数。一般是将当前可用资源数设置为最大资源数,每增加一个线程对共享资源的访问,当前可用资源数就会减1 ,只要当前可用资源数是大于0 的,就可以发出信号量信号。当前可用计数减小到 0 时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能再允许其他线程的进入,此时的信号量信号将无法发出。线程在处理完共享资源后,在离开的同时通过 ReleaseSemaphore() 函数将当前可用资源数加1 。在任何时候当前可用资源数决不可能大于最大资源数。
  2. 临界区:用来控制数据访问,它在任意时刻只允许一个线程对共享资源进行访问。
  3. Java中线程同步的方法有:
    • 用Synchronized关键字修饰方法,由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。Synchronized也可以修饰同步代码块,被该关键字修饰的语句会被加上内置锁,从而实现同步。但同步其实是个开销比较大的操作,通常没有同步整个方法的必要,所以在使用Synchronized时,尽量同步关键代码块即可。它
    • ReentrantLock与Synchronized类似,也能像Synchronized那样实现线程同步,同时它相比Synchronized扩展了一些额外的功能,比如可以指定是公平锁还是非公平锁,而synchronized只能是非公平锁;还有等待可中断: 正在等待的线程可以放弃等待,改为处理其他事情。而 synchronized 不行。
    • Volatile:提供的是一种免锁机制。它将线程修改的值写入主内存,并使其他线程工作内存里对应的这个数据失效,这些线程想再次读取这个数据时就重新去主内存中读取,通过这种可见性使每个线程访问到的变量值是一样的,这样就保证了同步。

你可能感兴趣的:(Thread-多线程系列)