线程基础
一、线程安全
1.1概念:当多个线程访问某一个类(对象或者方法)时,这个类始终都能表现出正确额行为,那么这个类(对象或者方法)就是线程安全的。
1.2synchronized :可以在任何对象或者方法上加锁,二加锁的这段代码称为“互斥区”或者临界区。
例子:
package com.nbkj.thread;
/**
* @author hsj
*
*/
public class MyThread extends Thread {
private static int count = 20;
@Override
public synchronized void run() {
count--;
System.out.println("count的值是:" + count);
System.out.println("当前的线程是:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
/*MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
MyThread t4 = new MyThread();
MyThread t5 = new MyThread();
MyThread t6 = new MyThread();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();*/
MyThread myThread=new MyThread();
Thread t1=new Thread(myThread,"t1");
Thread t2=new Thread(myThread,"t2");
Thread t3=new Thread(myThread,"t3");
Thread t4=new Thread(myThread,"t4");
Thread t5=new Thread(myThread,"t5");
Thread t6=new Thread(myThread,"t6");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
总结:
当多个线程访问MyThread的run方法的时候,以排队的方式进行处理(按照cpu分配的的顺序),一个线程要是想要执行synchronized修饰的方法里的代码,首先是尝试获得锁,如果拿到锁,执行synchronized代码内容,拿不到,这个线程就会尝试获得这把锁,直到拿到,多个线程去竞争这把锁,(锁竞争问题)
1.3多个线程多个锁
多个线程多个锁:多个线程,每个线程都可以拿到指定的锁,分别获得锁之后执行synchronized方法体的内容。
示例:
package com.nbkj.thread;
/**
* 多个线程多个锁
*
* @author bingshu
*
*/
public class MultiThread {
private static int num = 0;
public static synchronized void pringNum(String tag) {
try {
if (tag.equals("a")) {
num = 100;
System.out.println("tag a set num over");
Thread.sleep(1000);
} else {
num = 200;
System.out.println("tag b set num over");
}
System.out.println("tag " + tag + ",num" + num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
final MultiThread m1 = new MultiThread();
final MultiThread m2 = new MultiThread();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.pringNum("a");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.pringNum("b");
}
});
t1.start();
t2.start();
}
}
总结:
关键字synchronized取得都是对象锁,而不是把一段代码(方法)当做锁,所以示例代码中哪个线程执行synchronized关键字的方法,那个线程就持有该方法所属对象的锁,两个对象,线程获得是两把不同的锁,他们互不影响。
注意:
有一种情况是相同的锁,即在静态方法上加锁synchronized关键字,表示锁定当前class类,类级别的锁。(独占.class类)
1.4对象锁的同步和异步
同步:synchronized
同步的概念就是共享,我们要牢记“共享”这两个字,如果不是共享的资源就没必要同步。
异步:asynchronized
异步的概念就是独立,相互之间不受任何制约,就像http的时候,在页面发起ajax请求,我们还可以继续浏览和操作页面内容,而知没有任何关系
同步的目的就是为了线程安全,对于线程安全来说,需要满足两个特性:
原子性(同步)
可见性
示例:
package com.nbkj.thread;
public class MyObject {
public synchronized void method1() {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/* synchronized */
public void method2() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
final MyObject myObject = new MyObject();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
myObject.method1();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
myObject.method2();
}
}, "t2");
t1.start();
t2.start();
}
}
总结:
当method2中加synchronized的时候 t1获得锁,需等待t1执行完毕释放锁的时候,t2才能执行method2。
当method2不加synchronized的时候是异步执行,不需要获得锁,没有什么关系。