In python, I have a global variable defined that gets read/incremented by different threads. Because of the GIL, will this ever cause problems without using any kind of locking mechanism?
Yes, multithreading without locking almost always causes problems, with or without a GIL.
Short answer: Don't assume this to be safe. You have no guarantee that the implementation of the language won't change out from underneath you; for instance, your code could be running on Stackless, or Jython, or IronPython at some point in the future. Assuming the GIL will take care of this (i.e. the implementation implies the GIL is present) means that you will, at some point, have something break.
The GIL only requires that the interpreter completely executes a single bytecode instruction before another thread can take over. However, there is no reason to assume that an increment operation is a single instruction. For example:
>>> import dis
>>> dis.dis(compile("x=753","","exec"))
1 0 LOAD_CONST 0 (753)
3 STORE_NAME 0 (x)
6 LOAD_CONST 1 (None)
9 RETURN_VALUE
>>> dis.dis(compile("x+=1","","exec"))
1 0 LOAD_NAME 0 (x)
3 LOAD_CONST 0 (1)
6 INPLACE_ADD
7 STORE_NAME 0 (x)
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
As you can see, even these simple operations are more than a single bytecode instruction. Therefore, whenever sharing data between threads, you must use a separate locking mechanism (eg, threading.lock) in order to maintain data consistency.