并发和并行
并发和并行的区别就是一个处理器同时处理多个任务和多个处理器或者是多核的处理器同时处理多个不同的任务.前者是逻辑上的同时发生,而后者是物理上的同时发生.
并发在微观上不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行,从宏观外来看,好像是这些进程都在执行。
并行是指无论从微观还是宏观,二者都是一起执行的
并发在单核和多核都可存在,就是同一时间有多个可以执行的进程。
并行是指同一时间多个进程在微观上都在真正的执行,这就只有在多核的情况下了。
多线程是并发
多线程的同步与异步
共享资源:都可以访问的资源
临界区:指的是一个访问共享资源的程序片段
临界资源:临界资源是一次仅允许一个进程或线程使用的共享资源
同步:就是同一时间只有一个线程访问共享资源
异步:同一时间A线程访问共享资源B线程也可以访问共享资源
同步最最安全,最保险的。而异步不安全,容易导致死锁,这样一个线程死掉就会导致整个
进程崩溃,但没有同步机制的存在,性能会有所提升
多线程同步的方式
在JAVA中,是没有类似于PV操作、互斥等相关的方法的。JAVA线程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。
同步的方式:同步代码块,同步方法
同步代码块
格式:
Synchronized(同步对象){
需要同步的代码;
}
class MyThread implements Runnable{
int ticket=5;
public void run(){
synchronized(this){ //同步代码块,同步当前对象
for(int i=0;i<50;i++){
if(ticket>0){
try{
Thread.sleep(300);
}catch(InterruptedException e){
e.getStackTrace();
}
System.out.println("卖票"+(ticket--));
}
}
}
}
}
public class Test
{
public static void main(String args[]){
MyThread m1=new MyThread();
new Thread(m1).start();
new Thread(m1).start();
new Thread(m1).start();
}
}
同步方法
synchronized关键字修饰方法
class MyThread implements Runnable {
int ticket = 5;
public void run() {
for (int i = 0; i < 50; i++) {
this.sale(); //调用当前类中的同步方法
}
}
public synchronized void sale() { //同步方法
if (ticket > 0) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.getStackTrace();
}
System.out.println("卖票" + (ticket--));
}
}
}
public class Test {
public static void main(String args[]) {
MyThread m1 = new MyThread();
new Thread(m1).start();
new Thread(m1).start();
new Thread(m1).start();
}
}
注
Java中的每个对象都有一个锁(lock),或者叫做监视器(monitor),当一个线程访问某个对象的synchronized方法时,将该对象上锁,其他任何线程都无法再去访问该对象的synchronized方法了。直到之前的那个线程执行方法完毕后(或者是抛出了异常),才将该对象的锁释放掉,其他线程才有可能再去访问该对象的synchronized方法。
注意这时候是给对象上锁,如果是不同的对象,则各个对象之间没有限制关系。
死锁
导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问,使两个或者多个线程之间相互等待,导致线程都无法执行。
产生死锁的条件:
1.有至少一个资源不能共享
2.至少有一个任务必须持有一个资源并且等待获取另一个被别的任务持有的资源
3.资源不能任务抢占
4.必须有循环等待