一个程序,多个线程同时操作一个变量,给这个变量+1()。功能很简单,可是怎么样去实现呢?这其中涉及到了哪些问题?

最基础想法

见代码:

 public class Test extends Thread {
public static int amount = 0; public void run() {
amount++;
} public static void main(String[] args) {
int num_thread = 100;
for (int i = 0; i < num_thread; i++) {
new Test().start();
}
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(amount);
}
}

输出结果:

num_thread = 100时,结果=100;

num_thread = 1000时,结果=1000;

num_thread = 10000时,结果=9995;

num_thread = 1000000时,结果=999936;

程序判定为不安全,当线程数比较少的时候,因为线程是先后启动的,所以看起来没有影响,一旦线程数增大,弊端毕露无疑。其实还有一个更简单看出问题的方法,线程运行时,不是给变量+1,而是+1000*1000,再来看结果:

num_thread = 10时,结果=5034021;——线程数很少,但是结果不是想要的结果。

总之说明,这样的多线程不安全!amount++这个方法并不是原子性的!

升级想法1.0:用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新值。

见代码:

 public class Test extends Thread {
public static volatile int amount = 0;//只是这里的变量声明为volatile修饰 public void run() {
int i = 0;
while (i < 1000 * 1000) {
amount++;
i++;
}
} public static void main(String[] args) {
int num_thread = 10;
for (int i = 0; i < num_thread; i++) {
new Test().start();
}
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(amount);
}
}

输出结果:

num_thread = 10时,结果=2375833;——结果仍然不是想要的。

那问题出在哪里了呢?处在了对volatile修饰符的理解上。(参考博客:java中volatile关键字的含义

volatile很容易被误用,被误用来进行原子性操作。

在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图描述这种交互:

read and load      ——从主存复制变量到当前工作内存
use and assign    ——执行代码,改变共享变量值 
store and write    ——用工作内存数据刷新主存相关内容

其中use and assign 可以多次出现,但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样。

对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的

这项问题搞清楚之后可以继续想法了。

升级想法3.0:同步代码块——通过 synchronized 关键字,所有加上synchronized 的块语句,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized 修饰的方法或者代码块。

java为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。

对于synchronized的使用,又有不同的方式:同步代码块和同步方法

首先来看同步代码块的运用。语法见代码:

synchronized(syncObject){  
//code  
}

synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject 的锁方能执行。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

这里面的syncObject,可以是 类实例 或 类。

针对我们的场景,修改代码如下:

 public class Test extends Thread {
public static volatile Integer amount = new Integer(0);//修改为对象 public void run() {
int i = 0;
synchronized (amount) {
while (i < 1000 * 1000) {
amount++;
i++;
}
}
} public static void main(String[] args) {
int num_thread = 10;
for (int i = 0; i < num_thread; i++) {
new Test().start();
}
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(amount);
}
}

变动包括,amount的类型由int变为Interger,这样amount才是一个可以被synchronized使用的Integer实例。

然而程序的输出:1902241   —— 仍然不是我们想要的。问题出在了哪里?测试发现在synchronized后面sleep 10ms 以上同步成功,sleep 1ms 的话就不会成功!!!!!!!!!!!什么鬼!!!!!!!!详情见代码注释:

 public class Test implements Runnable {
// public static volatile AtomicInteger amount = new AtomicInteger(0);
private Integer amount = new Integer(0);
private InClass inClass = new InClass("adfas"); public void run() {
synchronized (amount) {
// synchronized (inClass) {// 注意!!这里换成inClass就成功了,即便没有sleep,简直郁闷啊啊啊啊啊!!!
// synchronized (this){ 或者synchronized (Test.class)都可以,即便没有sleep
System.out.println(
Thread.currentThread().getName() + "---------begin--------------" + System.currentTimeMillis());
try {
Thread.sleep(1);//sleep(10)的话可以成功,查看输出,程序输出时间确实是递增的!!!
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
for (int i = 0; i < 200000;) {
// addOne();
amount++;
i++;
}
System.out.println(
Thread.currentThread().getName() + "------------end-------------" + System.currentTimeMillis());
}
} public synchronized void addOne() {
amount++;
} public static void main(String[] args) {
int num_thread = 50;
Test test = new Test();
for (int i = 0; i < num_thread; i++) {
(new Thread(test)).start();
}
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(test.amount);
} class InClass {
public InClass(String name) {
// TODO 自动生成的构造函数存根
}
}
}

对于上面这个例子,是我最大的疑惑。讲道理的话,amount是一个Integer的实例,我本认为synchronized(amount)锁住的是amount这个实例的同步方法或者同步代码块,按道理来说对程序是没有影响的,也就是synchronized并不起作用,但是使用inClass实例告诉我们,上面的想法是错误的(具体原因需要分析)!但是既然synchronized(syncObject)表明了可以用的话,amount抽象来看,和inClass是同一个东西,都是实例!但是amount为什么就不能用呢???感觉非常奇怪,贴一下测试结果:

测试结果1:synchronized(amount)没有sleep(),可以明显看出,代码块没有被锁住。另外,sleep(1)的时候,结果类似。

Thread-0---------begin--------------1483240909596
Thread-7---------begin--------------1483240909596
Thread-9---------begin--------------1483240909597
Thread-10---------begin--------------1483240909597
Thread-11---------begin--------------1483240909598
Thread-12---------begin--------------1483240909603
Thread-8---------begin--------------1483240909617
Thread-18---------begin--------------1483240909617
Thread-9------------end-------------1483240909628
Thread-17---------begin--------------1483240909628
Thread-10------------end-------------1483240909631
Thread-12------------end-------------1483240909631
Thread-16---------begin--------------1483240909632
Thread-20---------begin--------------1483240909632
Thread-11------------end-------------1483240909632
Thread-19---------begin--------------1483240909633
Thread-18------------end-------------1483240909636
Thread-13---------begin--------------1483240909636
Thread-14---------begin--------------1483240909632
Thread-15---------begin--------------1483240909651
Thread-48---------begin--------------1483240909651
Thread-49---------begin--------------1483240909654
Thread-20------------end-------------1483240909654
Thread-13------------end-------------1483240909655
Thread-22---------begin--------------1483240909651
Thread-30---------begin--------------1483240909651
Thread-14------------end-------------1483240909669
Thread-23---------begin--------------1483240909651
Thread-15------------end-------------1483240909670
Thread-16------------end-------------1483240909651
Thread-7------------end-------------1483240909642
Thread-31---------begin--------------1483240909651
Thread-48------------end-------------1483240909673
Thread-38---------begin--------------1483240909651
Thread-39---------begin--------------1483240909651
Thread-30------------end-------------1483240909674
Thread-46---------begin--------------1483240909651
Thread-22------------end-------------1483240909674
Thread-26---------begin--------------1483240909651
Thread-23------------end-------------1483240909686
Thread-34---------begin--------------1483240909650
Thread-42---------begin--------------1483240909650
Thread-21---------begin--------------1483240909650
Thread-25---------begin--------------1483240909650
Thread-38------------end-------------1483240909693
Thread-31------------end-------------1483240909694
Thread-28---------begin--------------1483240909650
Thread-26------------end-------------1483240909695
Thread-29---------begin--------------1483240909650
Thread-37---------begin--------------1483240909650
Thread-36---------begin--------------1483240909650
Thread-34------------end-------------1483240909705
Thread-25------------end-------------1483240909709
Thread-44---------begin--------------1483240909650
Thread-21------------end-------------1483240909711
Thread-33---------begin--------------1483240909650
Thread-28------------end-------------1483240909713
Thread-41---------begin--------------1483240909650
Thread-45---------begin--------------1483240909650
Thread-29------------end-------------1483240909713
Thread-35---------begin--------------1483240909650
Thread-42------------end-------------1483240909714
Thread-27---------begin--------------1483240909650
Thread-17------------end-------------1483240909650
Thread-24---------begin--------------1483240909650
Thread-32---------begin--------------1483240909650
Thread-44------------end-------------1483240909730
Thread-40---------begin--------------1483240909650
Thread-41------------end-------------1483240909732
Thread-35------------end-------------1483240909733
Thread-19------------end-------------1483240909650
Thread-43---------begin--------------1483240909650
Thread-0------------end-------------1483240909650
Thread-6---------begin--------------1483240909734
Thread-8------------end-------------1483240909644
Thread-45------------end-------------1483240909735
Thread-33------------end-------------1483240909733
Thread-37------------end-------------1483240909722
Thread-36------------end-------------1483240909722
Thread-39------------end-------------1483240909691
Thread-46------------end-------------1483240909691
Thread-49------------end-------------1483240909674
Thread-47---------begin--------------1483240909657
Thread-27------------end-------------1483240909740
Thread-24------------end-------------1483240909740
Thread-32------------end-------------1483240909741
Thread-40------------end-------------1483240909748
Thread-6------------end-------------1483240909751
Thread-5---------begin--------------1483240909751
Thread-43------------end-------------1483240909751
Thread-47------------end-------------1483240909751
Thread-5------------end-------------1483240909752
Thread-4---------begin--------------1483240909752
Thread-4------------end-------------1483240909754
Thread-3---------begin--------------1483240909754
Thread-3------------end-------------1483240909756
Thread-2---------begin--------------1483240909756
Thread-2------------end-------------1483240909757
Thread-1---------begin--------------1483240909757
Thread-1------------end-------------1483240909758
2589439

测试结果2:synchronized(amount)并且sleep(10),可以看出,代码是被同步了的。为了看的更清楚,sleep(1000),结果类似。

Thread-0---------begin--------------1483241058337
Thread-0------------end-------------1483241058353
Thread-49---------begin--------------1483241058353
Thread-49------------end-------------1483241058365
Thread-48---------begin--------------1483241058365
Thread-48------------end-------------1483241058378
Thread-47---------begin--------------1483241058379
Thread-47------------end-------------1483241058390
Thread-46---------begin--------------1483241058390
Thread-46------------end-------------1483241058401
Thread-45---------begin--------------1483241058401
Thread-45------------end-------------1483241058412
Thread-44---------begin--------------1483241058412
Thread-44------------end-------------1483241058423
Thread-43---------begin--------------1483241058423
Thread-43------------end-------------1483241058434
Thread-42---------begin--------------1483241058434
Thread-42------------end-------------1483241058446
Thread-41---------begin--------------1483241058446
Thread-41------------end-------------1483241058461
Thread-40---------begin--------------1483241058461
Thread-40------------end-------------1483241058472
Thread-39---------begin--------------1483241058472
Thread-39------------end-------------1483241058483
Thread-38---------begin--------------1483241058483
Thread-38------------end-------------1483241058494
Thread-37---------begin--------------1483241058494
Thread-37------------end-------------1483241058504
Thread-36---------begin--------------1483241058504
Thread-36------------end-------------1483241058515
Thread-35---------begin--------------1483241058516
Thread-35------------end-------------1483241058526
Thread-34---------begin--------------1483241058526
Thread-34------------end-------------1483241058540
Thread-33---------begin--------------1483241058541
Thread-33------------end-------------1483241058552
Thread-32---------begin--------------1483241058552
Thread-32------------end-------------1483241058563
Thread-31---------begin--------------1483241058564
Thread-31------------end-------------1483241058577
Thread-29---------begin--------------1483241058577
Thread-29------------end-------------1483241058588
Thread-30---------begin--------------1483241058588
Thread-30------------end-------------1483241058598
Thread-28---------begin--------------1483241058599
Thread-28------------end-------------1483241058610
Thread-27---------begin--------------1483241058610
Thread-27------------end-------------1483241058621
Thread-26---------begin--------------1483241058621
Thread-26------------end-------------1483241058632
Thread-25---------begin--------------1483241058632
Thread-25------------end-------------1483241058643
Thread-24---------begin--------------1483241058643
Thread-24------------end-------------1483241058654
Thread-23---------begin--------------1483241058654
Thread-23------------end-------------1483241058665
Thread-22---------begin--------------1483241058665
Thread-22------------end-------------1483241058680
Thread-21---------begin--------------1483241058680
Thread-21------------end-------------1483241058693
Thread-20---------begin--------------1483241058693
Thread-20------------end-------------1483241058706
Thread-19---------begin--------------1483241058706
Thread-19------------end-------------1483241058718
Thread-18---------begin--------------1483241058718
Thread-18------------end-------------1483241058731
Thread-17---------begin--------------1483241058731
Thread-17------------end-------------1483241058743
Thread-16---------begin--------------1483241058743
Thread-16------------end-------------1483241058757
Thread-15---------begin--------------1483241058757
Thread-15------------end-------------1483241058770
Thread-14---------begin--------------1483241058772
Thread-14------------end-------------1483241058783
Thread-13---------begin--------------1483241058783
Thread-13------------end-------------1483241058794
Thread-12---------begin--------------1483241058794
Thread-12------------end-------------1483241058805
Thread-11---------begin--------------1483241058805
Thread-11------------end-------------1483241058816
Thread-10---------begin--------------1483241058817
Thread-10------------end-------------1483241058828
Thread-9---------begin--------------1483241058828
Thread-9------------end-------------1483241058839
Thread-8---------begin--------------1483241058839
Thread-8------------end-------------1483241058850
Thread-7---------begin--------------1483241058850
Thread-7------------end-------------1483241058861
Thread-6---------begin--------------1483241058861
Thread-6------------end-------------1483241058872
Thread-3---------begin--------------1483241058872
Thread-3------------end-------------1483241058883
Thread-5---------begin--------------1483241058883
Thread-5------------end-------------1483241058895
Thread-4---------begin--------------1483241058896
Thread-4------------end-------------1483241058907
Thread-2---------begin--------------1483241058907
Thread-2------------end-------------1483241058919
Thread-1---------begin--------------1483241058919
Thread-1------------end-------------1483241058930

升级想法3.1:基于上面出现的各种问题,可以把amount++这一步直接用一个synchronized修饰的方法代替,简单明了,粗暴高效!

详见上面的代码里面的addOne()方法!但是这里其实是有问题的:毕竟真是程序中一般可能出现各种同步情况,很多时候同步代码块儿的灵活性非常好,而同步方法使用起来可能不方便;所以上面的问题还是需要解决,在网上很多的例子中我们看到的都是synchronized(this)和synchronized(Test.class),关于这两种用法的对比,见之后的补充。当我们不想锁住类的对象,只是想同步代码块的时候,可以考虑创建一个对象实例,如下图所示:

升级想法4.0:java里面有些对数变量的操作是原子性的,

Java中的原子操作包括:
1)除long和double之外的基本类型的赋值操作
2)所有引用reference的赋值操作
3)java.concurrent.Atomic.* 包中所有类的一切操作
count++不是原子操作,是3个原子操作组合
1.读取主存中的count值,赋值给一个局部成员变量tmp
2.tmp+1
3.将tmp赋值给count

方法:使用java.util.concurrent.AtomicInteger,详见代码!

 import java.util.concurrent.atomic.AtomicInteger;

 public class Test implements Runnable {
public static volatile AtomicInteger amount = new AtomicInteger(0); public void run() {
System.out.println(
Thread.currentThread().getName() + "---------begin--------------" + System.currentTimeMillis());
for (int i = 0; i < 200000;) {
amount.incrementAndGet();
i++;
}
System.out.println(
Thread.currentThread().getName() + "------------end-------------" + System.currentTimeMillis());
}
} public static void main(String[] args) {
int num_thread = 50;
Test test = new Test();
for (int i = 0; i < num_thread; i++) {
(new Thread(test)).start();
}
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(test.amount);
} }

另外补充!synchronized(this) VS synchronize(MyClass.class)

引用国外一个问答网站的精辟回答:

"

MyClass.class and this are different things, are different references to different objects.

this - is the reference to particular this instance of class, and

MyClass.class - is the reference to MyClass description object.

This synchronization blocks differs in that the first will synchronize all threads that deal concretely with this instance of MyClass, and the second one will synchronize all threads independently of which object on which this method was called.

"

翻译过来就是:this同步的是一个具体的对象,所有由这个对象产生的线程在运行同一个方法时都会被阻塞(补充:所有的synchronized标示的方法用也会被阻塞,原因是等同1);MyClass.class同步的是当前类,获取锁的方法将阻塞所有这个类的实例对象,这些对象都无权调用该方法。理解这里的this和MyClass.class非常重要!比如对于上面的例子来说,如果我们的Test extends Thread,如果每次启动线程都是new Test().start(),使用synchronized(this)是无效的(程序中amount要声明为static,属于类),因为每个线程都是一个独立的对象产生的。(注意下面两个等同)。

 等同1:

public void test() {
synchronized(this) {
// todo your code
}
}
public synchronized void test() {
// todo your code
}

等同2:

如果某方法为类方法,即其修饰符为static,那么synchronized 意味着某个调用此方法的线程当前会拥有该类的锁,只要该线程持续在当前方法内运行,其他线程依然无法获得方法的使用权!

测试代码:

 public class TestSynchronized {
private InClass inClass = new InClass("name"); public void test1() {
synchronized (inClass) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
} public synchronized void test2() { int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
} } public void test3() {
synchronized (TestSynchronized.class) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
} public void test4() {
synchronized (this) {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
} public synchronized void test5() { int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
} } public static void main(String[] args) {
final TestSynchronized myt1 = new TestSynchronized();
final TestSynchronized myt2 = new TestSynchronized();
Thread test1 = new Thread(new Runnable() {
public void run() {
myt1.test2();
}
}, "test1");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
Thread test2 = new Thread(new Runnable() {
public void run() {
myt1.test5();
}
}, "test2");
test1.start();
test2.start();
} class InClass {
public InClass(String name) {
// TODO 自动生成的构造函数存根
}
}
}

测试会发现,synchronized(this)会锁住代码块本身的方法、synchronized标示的方法和其它synchroized(this)的代码块;而synchronized(MyClass.class)只能锁住不同对象对应的这一个方法块儿!其他方法(即便是同步的)不会被锁住!

纸上得来终觉浅,还盼诸君勤实践啊!!!啊啊啊啊啊啊!!!!!

参考:synchronize类锁和对象锁详解深入理解java中的synchronized关键字java中volatile关键字的含义(这个的评论要看一下)

-------------------------------------- 我 是 华 丽 的 分 割 线 ------------------------------------------

--->>>原因找到了!
关键在于amount is an instance of Integer,synchronized锁的是amount这个对象,但是for循环中amount++这个操作会使得amount这个对象发生变化,这个通过hashcode可以看出来,对于instance of Integer,amount.intValue()==amount.hashcode().所以当这个对象变了之后,之前对象的锁自然就没用了,其它线程开始竞争新对象的锁,由此造成了这样的结果。

--->>>关于synchronized一点补充

synchronized的实现机制需要参照jvm,了解的知识比较多。synchronized(syncObject)类似于给某个对象加锁,{\\code}代码块里面的东西在执行之前都需要获取这把锁,运行完之后马上释放锁。

一个简单的synchronized多线程问题、梳理与思考的更多相关文章

  1. [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程

    一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...

  2. 一个简单的Python多线程

    首先对一段普通的代码进行测试 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" import time def RunThrea ...

  3. Java网络与多线程系列之1:实现一个简单的对象池

    前言 为什么要从对象池开始呢,先从一个网络IO操作的demo说起 比如下面这段代码,显而易见已经在代码中使用了一个固定大小的线程池,所以现在的重点在实现Runnble接口的匿名对象上,这个对象每次创建 ...

  4. 一个简单的多线程Python爬虫(一)

    一个简单的多线程Python爬虫 最近想要抓取拉勾网的数据,最开始是使用Scrapy的,但是遇到了下面两个问题: 前端页面是用JS模板引擎生成的 接口主要是用POST提交参数的 目前不会处理使用JS模 ...

  5. Java Tread多线程(0)一个简单的多线程实例

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39341887 本文演示,一个简单的多线程实例,并简单分析一下线程. 编程多 ...

  6. C语言多线程的一个简单例子

    多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  7. Qt5.9一个简单的多线程实例(类QThread)(第一种方法)

    Qt开启多线程,主要用到类QThread.有两种方法,第一种用一个类继承QThread,然后重新改写虚函数run().当要开启新线程时,只需要实例该类,然后调用函数start(),就可以开启一条多线程 ...

  8. [MFC] 梳理一个简单的图片处理桌面软件中用到的MFC控件技巧

     前言 前些天应好友之拖,帮忙设计一个简单的图像处理的小软件.朋友把核心算法封装好了,但是是用openCV类似于console的编程环境,要我在此基础上改成MFC桌面程序.下图是做成之后的效果: 我是 ...

  9. 一个简单的HTTP服务器(多线程)

    为了更好的了解HTTP协议, 特意谢了一个简单HTTP服务器, 代码只有400行. 因为很简单, 所以效率也不怎么高, 而且支持的特性也不多, 不过也可以运行, 性能跟Apache差不多. ===== ...

随机推荐

  1. 报错:org.hibernate.AssertionFailure: null id in com.tt.hibernate.entities.News entry (don't flush the Session after an exception occurs)

    在使用hibernate创建数据库的表格时,出现了如下报错: 十二月 28, 2016 10:17:02 上午 org.hibernate.tool.hbm2ddl.SchemaExport perf ...

  2. c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast

    C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...

  3. Gulp安装及配合组件构建前端开发一体化

    原文:http://www.dbpoo.com/getting-started-with-gulp/ 所有功能前提需要安装nodejs(本人安装版本v0.10.26)和ruby(本人安装版本1.9.3 ...

  4. Sql服务定时重启

    net stop sqlserveragentnet stop mssqlservernet start mssqlservernet start sqlserveragent 保存到记事本中,重命名 ...

  5. mysql replication

    change master to master_host='192.168.0.3',master_user='myrepl',master_password='5rNUnOHxut3lkP4wXds ...

  6. Android Studio 高级配置

    http://liukun.engineer/2016/04/10/Android-Studio-advanced-configuration/

  7. U盘安装CentOS 7.0

    U盘安装CentOS 7.0 由于学习需要centos环境,so上网下载centos安装镜像,发现版本已经到7.0了,(╮(╯▽╰)╭,上次折腾还是6.4的版本呢,)花了一点时间下载下来按照装6.4的 ...

  8. logstash 配置 logstash-forwarder (前名称:lumberjack)

    logstash-forwarder(曾名lumberjack)是一个用go语言写的日志发送端, 主要是为一些机器性能不足,有性能强迫症的患者准备的. 主要功能: 通过配置的信任关系,把被监控机器的日 ...

  9. [转]云计算研究必备——精典Google论文

    Google云计算技术奠定其在业界的领先地位,收集经典云计算技术公开文章供大家研究学习: 01)GFS-The Google File System 02) Bigtable - A Distribu ...

  10. Linux常用命令集合

    常用的Linux命令,备忘 1 pwd 显示当前目录 命令格式: pwd [选项] 2 cd 更换目录 命令格式: cd [目录名] 例: 3 ls 显示当前目录内容 命令格式: ls [选项] [目 ...