上面是设置, runtime.GOMAXPROCS(4), 下面是 runtime.GOMAXPROCS(1), 执行时间差了4倍。
------------------
对于多核编程,go是天生支持,那么我们在什么情况下应该用多核心来加速程序,而在什么情况下用单核即可呢?
现在我们用一简单的程序来说明下:
package main import ( "runtime" "fmt" "sync" "database/sql" _ "github.com/go-sql-driver/mysql" "time" ) //定义任务队列 var waitgroup sync.WaitGroup func xtgxiso(num int) { //fmt.Println(num) db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8") if err != nil { fmt.Println(err) } defer db.Close() rows, err := db.Query("select sleep(1) as a") if err != nil { fmt.Println(err) } defer rows.Close() var a string for rows.Next() { err = rows.Scan(&a) if err != nil { fmt.Println(err) } else { //fmt.Println(a) } } waitgroup.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1) } func main() { //记录开始时间 start := time.Now() //设置最大的可同时使用线程数 runtime.GOMAXPROCS(1) for i := 1; i <= 10; i++ { waitgroup.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1 go xtgxiso(i) } waitgroup.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞 //记录结束时间 end := time.Now() //输出执行时间,单位为秒。 fmt.Println(end.Sub(start).Seconds()) }
这个程序是执行十次”select sleep(1) as a“.如果是顺序阻塞执行的话,执行时间肯定是10s以上,而我们用的协程不会有这种情况。
我们可以修改“runtime.GOMAXPROCS(1)”来设置最大可同时执行的线程数,对比结果发现,都是1s多点,有时多线程反而会比单线程慢些,这是为什么呢?
这是因为这个程序是IO为主的,启用多线程反而有上下文切换,所以对于以涉及IO操作的主的程序启用多线程对于加速程序意义不大,
runtime.GOMAXPROCS(1) 保证了mysql的操作(golang底层走的是非阻塞io)都在一个线程上执行,也就没有了cpu在多个线程之间来回调度。
那么什么程序启用多线程呢?我们来看如下程序:
package main import ( "runtime" "fmt" "sync" "time" ) //定义任务队列 var waitgroup sync.WaitGroup func xtgxiso(num int) { for i:=1;i<=1000000000;i++{ num = num+i num = num-i num = num*i num = num/i } waitgroup.Done() //任务完成,将任务队列中的任务数量-1,其实.Done就是.Add(-1) } func main() { //记录开始时间 start := time.Now() //设置最大的可同时使用的线程数 runtime.GOMAXPROCS(1) for i := 1; i <= 10; i++ { waitgroup.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1 go xtgxiso(i) } waitgroup.Wait() //Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞 线//记录结束时间 end := time.Now() //输出执行时间,单位为秒。 fmt.Println(end.Sub(start).Seconds()) }
对比结果发现,多线程比单线程快,所以对于CPU的运行上,多线程运行加速效果是很明显的.