线程并发一:概念理解

1.同步(Synchronous) 和异步(Asynchronous)

同步和异步通常来形容一次方法的调用,同步方法调用一旦开始,调用者必须等到方法调用结束才成继续后续的行为。异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回调用者可以继续后续的操作。如果异步调用需要返回结果,那么当这个异步调用真实完成时,则会通知调用者。

2.临界区
临界区一般用来表示多线程的共享资源数据。也就是并发情况下要保护的对象。

3.阻塞(Blocking)和非阻塞(Non-Blocking)
阻塞和非阻塞一般用来多线程之间的相互影响或对IO的操作。当一个线程占用了临界区的资源,其他线程线程在调用临界区资源的时候必须等待,等待会导致线程挂起,这种情况就是阻塞。如果当前线程不释放临界区资源,那么其他所用线程都将不能工作
非阻塞:强调没用一个线程可以妨碍其他线程执行,所用线程都会不断尝试获取临界区资源,获取不到直接返回,下次再获取。

4. 死锁(Deadlock)、饥饿(Starvation)、活锁(Livelock)
几种状态都属于多线程活跃性的问题,当出现这种问题的时候,也就表明相关线程出现了问题,很难再执行下去

死锁:是最糟糕的一个问题,是指两个或两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去。

死锁形成条件:
互斥条件:所谓互斥就是进程在某一时间内独占资源。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

死锁形成的常见情况有以下几种:

a.忘记释放锁

b.单线程重复申请锁

void sub_func()
{
    EnterCriticalSection();
    do_something();
    LeaveCriticalSection();
}
​
void data_process()
{
    EnterCriticalSection();
    sub_func();
    LeaveCriticalSection();
}

c.多线程多锁申请

void data_process1()
{
    EnterCriticalSection(&cs1);  // 申请锁的顺序有依赖
    EnterCriticalSection(&cs2);
    do_something1();
    LeaveCriticalSection(&cs2);
    LeaveCriticalSection(&cs1);
}
​
void data_process2()
{
    EnterCriticalSection(&cs2);  // 申请锁的顺序有依赖
    EnterCriticalSection(&cs1);
    do_something2();
    LeaveCriticalSection(&cs1);
    LeaveCriticalSection(&cs2);
}

d.环形锁申请
/* 多个线程申请锁的顺序形成相互依赖的环形:
* A - B
* | |
* C - D
*/

饥饿:是指线程因种种原因无法获取所需要的资源导致一直无法执行。
一般会出现饥饿状态有两种原因:
a.某一线程一直占用资源
b.线程优先级问题

活锁:是指线程1可以使用资源,但它很礼貌,让其他线程先使用资源,线程2也可以使用资源,但它很绅士,也让其他线程先使用资源。这样你让我,我让你,那么就会出现资源不断在两个线程中跳动,而没有一个线程可以同时拿到所用资源而正常执行

5.线程优先级
Java中线程可以有自己的优先级,优先级高的线程在竞争资源时会更有优势,但如果无法精准控制多线程的优先级,会导致低优先级的线程可能一直抢占不到资源,从而始终无法运行。所以设置线程优先级要谨慎。在Java中,使用1 到10 表示线程优先级。一般可以使用Thread 类中内置的三个静态标量表示:

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

执行下面的示例,可以看到高优先级的线程在大部分情况下都会先执行完任务。

public class PriorityDemo {

    public static class HightThread extends Thread {
        static int count = 0;
        public void run(){
            while (true){
                synchronized (PriorityDemo.class){
                    count ++;
                    if(count > 1000000){
                        System.out.println("HightThread is complete!");
                        break;
                    }
                }
            }
        }
    }

    public static class LowThread extends Thread {
        static int count = 0;
        public void run(){
            while (true){
                synchronized (PriorityDemo.class){
                    count ++;
                    if(count > 1000000){
                        System.out.println("LowThread is complete!");
                        break;
                    }
                }
            }
        }
    }

    public static void main(String[] args){
        Thread high = new HightThread();
        Thread low = new LowThread();

        high.setPriority(Thread.MAX_PRIORITY);
        low.setPriority(Thread.MIN_PRIORITY);
        low.start();
        high.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值