线程与进程

进程与线程

认知

1.进程与线程
进程:操作系统进行资源调度和分配的基本单位
线程:进程中的最小执行单位,是CPU资源分配的基本单位(可以理解为一个顺序的执行流).
说明:多个线程可以共享所属进程的所有资源
2.多线程的并发与并行
并发:多线程抢占CPU,可能不同时执行,侧重于多个任务交替执行
并行:线程可以不共享CPU,可每个CPU同时执行多个任务。
总结:并行只出现在多CPU或多核CPU中,而并发可理解为并行中的一个子集。
3.线程的生命周期
新建状态、就绪状态、运行状态、阻塞状态、死亡状态

安全问题

1.多个线程并发执行时,仍旧能够保证数据的正确性,这种现象称之为线程安全。
2.多个线程并发执行时,不能够保证数据的正确性,这正现象称之为线程不安全。
卖票案例:

class Test {
	public static void main(){
		Ticket ttask = new Ticket();
		Thread t1 = new Thread(task);
		Thread t2 = new Thread(task); 
		Thread t3 = new Thread(task); 
		Thread t4 = new Thread(task);
		t1.start();
		t2.start();
		t3.start();
		t4.start();  
	}
}
class TicketTask implements Runnable{
	int ticket = 100;
	@Override 
	public void run(){
		doTicket();
	}
	public void doTicket(){
		while(true){
			if(ticket<=0){
				break;
			}
			System.out.println(ticket--);
		}
	}
}

计数案例:

class Counter{
	private int count;
	public void doCount(){
		count++;
	}
}

导致多线程不安全的因素

1.多个线程并发执行
2.多个线程并发执行时存在共享数据集(临界资源);
3.多个线程在共享数据集上的操作不是原子操作(不可拆分的一个操作);

如何保证并发线程的安全

1.对共享进行限制(阻塞)访问(例如加锁:syncronized,Lock):多线程在同步方法或同步代码块上排队执行。
2.基于CAS(比较和交换)实现非阻塞同步(基于CPU硬件技术支持):
a.内存地址(V)
b.期望数据值(A)
c.需要更新的值(B)
CAS算法支持无所状态下的并发更新,但可能会出现ABA问题,长时间自旋问题。
3.取消共享,每个线程一个对象实例(例如ThreadLocal)
a. Connection 不允许多线程共享,每个线程一个。
b. SimpleDateFormat 不允许多线程共享,每个线程一个。
c. SqlSession 对象不允许共享,每个线程一个。
注:Java中的线程安全问题主要关注点有3个:可见性,有序性,原子性;Java内存模型(JMM)解决了可见性和有序性问题,而锁解决了原子性问题。

Synchromized关键字

1.synchronized简介
1)synchronized是排它锁的一种实现,支持可重入性。
2)基于这种机制可以实现多线程在共享数据集上同步(互斥与协作)。
2.1)互斥:多线程在共享数据集上排队执行。
2.2)协作:多线程在共享数据集上进行协作执行(通讯)。
说明:
排他性:如果线程T1已经持有锁L,则不允许除T1外的任何线程T持有该锁L
重入性:如果线程T1已经持有锁L,则允许T1多次获取锁L,更确切的说,获取一次后可多次进入锁。
2.Synchronized应用分析:
1)修饰方法:同步方法(锁为当前实例或Class对象)
1.1)修饰静态方法:默认使用的锁为方法所在类的Class对象
1.2)修饰实例方法:默认使用的锁为方法所在类的实例对象
2)修饰代码块:同步代码块(代码块括号内配置的对象)
3.Synchronized原理分析:基于Monitor对象实现同步。
1)同步代码块采用monitorenter、monitoreXit指令显示实现。
2)同步方法则使用ACC_SYNCHRONIZED标记符隐式的实现
4.Synchronized锁优化:底层
为了减少获得锁和释放锁带来的性能消耗,JDK1.6以后的锁一共有4种状态,级别从低到高依次是:无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态,这几个状态会随着竞争情况逐渐升级。
说明:锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。
5.如何理解volatile关键字的应用
1.定义:volatile一般用于修饰属性变量
1)保证共享变量的可见性(尤其是多核或多CPU场景下)
2)禁止指令的重排序操作(例如count++底层会有三个步骤)
3)不保证原子性(例如不能保证一个线程执行完count++所有指令其他线程才能执行)
2.应用场景分析:
1)状态标记(boolean类型属性)
2)安全发布(线程安全单例中的对象安全发布-双重检测机制)
3)读写锁策略(一个写,并发读,类似读写锁)
样例:
1.状态标记代码

class Looper{
	private volatile boolean isStop;
	public void loop(){
		for(;;){
			if(isStop)break;
		}
	}
	public void stop(){
		isStop=true;
	}
}
public class TestVolatile01{
	public static void main(String[] args) throw Exception{
		Thread t1 = new Thread(){
		public void run(){
			looper.loop();
		};
	};
	t1.start();
	t1.join(1000);
	looper.stop();
	}
}

2.安全发布

class Singleton{
	private Singleton(){}
	private static volatile Singleton instance;
	public static Singleton getSingleton(){
		if(instance==null){
		 	synchronized (Singleton.class){
				instance = new Singleton();
			}
		}
		return instance;
	}
}

3.读写锁应用案例

class Counter{
	private volatile int count;
	public int getCount(){//读
		return count;
	}
	public synchronized void doCount(){//写
		count++;
	}
}

悲观锁与乐观锁

1.悲观锁:假定会发生并发生冲突,屏蔽一切可违反数据完整性的操作,同意时刻只能有一个线程执行写操作
例如 Java中可以基于syncronized,lock,ReadWriteLock等实现。
2.乐观锁:假设不会发生冲突,只在提交操作时检查是否违反数据完整性。多个线程可以并发执行写操作,但只能有一个线程写操作成功。
例如 Java中可借助CAS算法实现(此算法依赖硬件CPU)
3.应用场景说明
1)悲观锁适合写操作比较多的场景,写可以保证写操作是数据正确
2)乐观锁适合读操作比较多的场景,不加锁的特点能够使其操作的性能大幅度提升。
4.案例
悲观锁实现计数器
方案一:

class Counter{
	private int count;
	public synchronized int count(){
		count++;
		return count;
	}
}

方案二

class Counter{
private int count;
private Lock lock = new ReentrantLock();
public int count(){
	lock.lock();
	try{
	  count++;
	  return count;
	}finally{
	   lock.unlock;
	}
  }
}

乐观锁实现计数器

class Counter{
	private AtomicInteger at = new AtomicInteger();
	public int count(){
		return at.incrementAndGet();
	}
}

其中AtomichInteger是基于CAS算法实现。

上下文切换

一个线程得到 CPU执行的时间是有限的。当次线程用完为其分配的CPU时间以后,cpu会切换到下一个线程执行。
在线程切换之前,线程需要将当前状态进行保存,以便下次再次获得cpu时间片石可以加载对应的状态以便继续执行剩下的任务。而这个切换福偶成是需要耗费时间的,会影响多线程程序的知心效率,所以在多线程时要减少线程间的频繁切换。
减少多线程上线文切换的方案
1)无锁并发编程:锁的竞争会带来线程上下文的切换
2)CAS算法:CAS算法在锁具更新方面,可以达到锁的效果
3)使用最少线程:壁面不必要的线程等待
4)使用携程:单线程完成多个任务的调度和切换,壁面多线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值