同步也称为并发 因为有多个线程访问同一份资源 所以要确保资源安全 加上同步后就可以线程安全
synchronized //锁
同步
一,同步方法
谁先抢到synchronized谁先进其余的等待
package study;
/**
*
* @author http://blog.csdn.net/thewaiting/
*
*/
public class ThreadDome implements Runnable {
//共同使用i资源
private int i = 5;
private boolean flag = true;
@Override
public void run() {
while (flag) {
//text1();
text2();
}
}
public static void main(String[] args) {
// 1),创建真实角色
ThreadDome td1 = new ThreadDome();
// 2),创建代理角色+真实角色的引用
Thread t1 = new Thread(td1, "线程 1 ");
Thread t2 = new Thread(td1, "线程 2 ");
// 3),调用.star()方法 启动线程
t1.start();
t2.start();
}
public synchronized void text2() {
if (i <= 0) {
flag = false;
return;//方法return
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i--);
}
public void text1() {
if (i <= 0) {
flag = false;
return;//方法return
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i--);
}
}
text()1运行结果截取
线程 1 0
线程 2 -1
text()2运行结果截取
线程 2 2
线程 2 1
二,同步块
谁先得到synchronized谁先进入块其余的等待
synchronized(引用类型|this|类.class ){
上锁的
}
public void text3() {
synchronized (this) {
if (i <= 0) {
flag = false;
return;// 方法return
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i--);
}
}
错误的锁定
锁定范围过小
// 锁定范围过小
public void text4() {
synchronized (this) {
if (i <= 0) {
flag = false;
return;// 方法return
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i--);
}
锁定资源不正确 要锁定进来获取资源的对象
//// 锁定资源不正确 要锁定进来获取资源的对象
public void text5() {
synchronized ((Integer)i) {
if (i <= 0) {
flag = false;
return;// 方法return
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + i--);
}
线程安全的效率慢
synchronized单利模式
package study;
/**
* 单例设计模式:确保一个类只有一个对象 类里面创建
* @author http://blog.csdn.net/thewaiting/
*
*/
public class ThreadDome {
public static void main(String[] args) {
ScThread scThread1 = new ScThread(100);
ScThread scThread2 = new ScThread(500);
scThread1.start();
scThread2.start();
}
}
class ScThread extends Thread{
private long time;
public ScThread(long time) {
this.time = time;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"创建"+Sc.getInstance(time));
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
//确保一个类只有一个对象 懒汉式
//1,构造器私有化,避免外部直接创造对象
//2,声明一个私有的静态对象
//3,创建一个对外的公共的静态方法访问该变量 如果变量没有对象,创建该对象
class Sc{
//声明一个私有的静态对象
private static Sc instance = null;//懒得创建对象使用时再创建对象 对应有饿汉式
//构造器私有化,避免外部直接创造对象
private Sc() {
}
//创建一个对外的公共的静态方法访问该变量 如果变量没有对象,创建该对象
public static Sc getInstance(long time) throws InterruptedException {
if (null==instance) {
Thread.sleep(time);//故意放大发生错误的概率
instance = new Sc();
}
return instance;
}
}
运行结果
Thread-0创建study.Sc@6b20e4e1
Thread-1创建study.Sc@7bedda88
修改为synchronized锁定方法
public static synchronized Sc getInstance(long time) throws InterruptedException
运行结果
Thread-0创建study.Sc@7bedda88
Thread-1创建study.Sc@7bedda88
锁定块
//双重检查
//创建一个对外的公共的静态方法访问该变量 如果变量没有对象,创建该对象
public static Sc getInstance(long time) throws InterruptedException {
if (null == instance) {//如果存在就返回instance效率提高 提高已经存在的对象的访问效率
synchronized (Sc.class) {// 锁定字节码信息
if (null == instance) {
Thread.sleep(time);// 故意放大发生错误的概率
instance = new Sc();
}
}
}
return instance;
}
运行结果
Thread-1创建study.Sc@12341ad6
Thread-0创建study.Sc@12341ad6